Gorm:如何将分组查询结果通过Pluck/Scan映射到指定结构体
问题描述
对主表分组查询后得到如下SQL结果:
col1 |count| ------+-----+ test1 |12123| test2 | 1323| test3 | 4223| test4 | 1031|
希望将该结果映射到如下Go结构体:
type Lalala struct { Test1 int64 Test2 int64 Test3 int64 Test4 int64 }
当前采用结构体数组接收后通过switch case赋值,写法不够优雅。尝试过直接映射但失败:
var response Lalala // 尝试的无效写法 ....Group("col1"). Pluck("count", gorm.Expr("col1= test1"), &response.Test1). Pluck("count", gorm.Expr("col1= test2")).Scan(&response.Test2).Error
同时存在疑问:调用Pluck("count", &[]int)无法获取count列数组,必须用包含{col1:string,count:int64}的结构体接收,似乎Pluck返回行而非列。目前临时方案是多次Pluck配合offset,寻求更优实现方式。
解决方案
方法1:SQL行转列直接映射
利用SQL条件聚合将行数据转为列,直接查询出与结构体字段匹配的结果,GORM可直接完成映射:
var response Lalala db.Table("主表名"). Select(` SUM(CASE WHEN col1 = 'test1' THEN count ELSE 0 END) as test1, SUM(CASE WHEN col1 = 'test2' THEN count ELSE 0 END) as test2, SUM(CASE WHEN col1 = 'test3' THEN count ELSE 0 END) as test3, SUM(CASE WHEN col1 = 'test4' THEN count ELSE 0 END) as test4 `). Group("col1"). // 保留原查询的分组逻辑,按需调整 Scan(&response)
该方式一步完成查询与映射,是最简洁优雅的实现。
方法2:Map中转赋值
先将查询结果存入临时结构体数组,再转成Map,最后给目标结构体赋值,替代繁琐的switch case:
// 临时结构体用于接收分组查询结果 type TempCount struct { Col1 string Count int64 } var tempList []TempCount db.Table("主表名").Group("col1").Select("col1, count").Scan(&tempList) var response Lalala countMap := make(map[string]int64) for _, item := range tempList { countMap[item.Col1] = item.Count } // 直接通过Map键值对赋值 response.Test1 = countMap["test1"] response.Test2 = countMap["test2"] response.Test3 = countMap["test3"] response.Test4 = countMap["test4"]
关于Pluck的疑问说明
GORM的Pluck用于查询单列数据到切片,但如果原分组查询返回多列(col1和count),直接Pluck("count")会因结果集包含多列而无法正确解析。若要单独获取count列,需确保查询仅返回count列:Select("count").Group("col1").Pluck("count", &counts),但此操作会丢失col1与count的对应关系,因此不适合当前场景。
内容的提问来源于stack exchange,提问作者Branchverse
相关产品推荐
相关产品推荐

