默认使用Grom Join查询的方法
使用Raw.Rows
SQL较为复杂,使用Raw原生SQL查询
var results []model.InstanceBillItemsUsage
var cost_unit string
var CostUnitSum float32
var TotalSum float32
var Percentage []uint
rows,err := aliDB.Db.Raw("SELECT cost_unit, SUM(pretax_amount) AS CostUnitSum,totals.TotalSum, CONCAT(FORMAT((SUM(pretax_amount) / totals.TotalSum) * 100, 2), '%') AS Percentage FROM instance_bill_items_usages JOIN ( SELECT SUM(pretax_amount) AS TotalSum FROM instance_bill_items_usages WHERE billing_date BETWEEN ? AND ? ) AS totals WHERE instance_bill_items_usages.billing_date BETWEEN ? AND ? GROUP BY cost_unit; ", startDate, endDate, startDate, endDate).
WithContext(aliDB.Ctx).Rows
defer rows.Close()
for rows.Next() {
rows.Scan(&cost_unit, &CostUnitSum, &TotalSum, &Percentage)
fmt.Println(results)
}
if err != nil {
fmt.Println(err)
}
但缺点是,像以上
totals.TotalSum
会被转换为[]uint8
类型是因为在某些情况下,数据库驱动返回的聚合函数结果(如 SUM、COUNT、AVG)可能以字节流形式返回,特别是在使用 GORM 进行查询时。[]uint8
实际上就是 Go 语言中的字节切片,对应于 SQL 查询结果中的 BLOB 或 TEXT 类型数据。
方法2 使用.Scan直接扫描
在 GORM 里处理这种情况的一种方法是,将该字段显式地扫描到正确的 Go 类型。例如,如果你期望
TotalSum
是一个float64
类型的值,可以在 GORM 查询后使用.Scan
方法将查询结果扫描到一个结构体或者变量中,且该结构体或变量中的字段具有期望的类型。
即可实现
强制指定扫描类型
type Result struct {
CostUnit string `gorm:"column:cost_unit"`
GroupSum float64 `gorm:"column:GroupSum"`
TotalSum float64 `gorm:"column:TotalSum"`
Percentage string `gorm:"column:Percentage"`
}
var results []Result
aliDB.Db.Raw("SELECT cost_unit, SUM(pretax_amount) AS CostUnitSum,totals.TotalSum, CONCAT(FORMAT((SUM(pretax_amount) / totals.TotalSum) * 100, 2), '%') AS Percentage FROM instance_bill_items_usages JOIN ( SELECT SUM(pretax_amount) AS TotalSum FROM instance_bill_items_usages WHERE billing_date BETWEEN ? AND ? ) AS totals WHERE instance_bill_items_usages.billing_date BETWEEN ? AND ? GROUP BY cost_unit; ", startDate, endDate, startDate, endDate).
WithContext(aliDB.Ctx).Scan(&results)
fmt.Println(results)