You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将原生关联SQL查询转换为Gorm查询并将结果映射到结构体

你用Exec方法无法获取查询结果的核心原因是,Exec 是Gorm提供给无返回结果集的写操作(增删改、DDL等)的方法,不会处理查询返回的行数据,查询操作需要使用Raw方法执行SQL,配合Scan将结果映射到结构体。

实现步骤

1. 定义结果接收结构体

首先定义和返回字段一一对应的结构体,用gorm:"column:xxx"标签映射SQL查询的列别名:

// 字段类型可根据你的实际表字段类型调整,比如UID为数字则将UserID改为int64,时间字段改为time.Time
type UserWinStat struct {
    FullName             string `gorm:"column:Full Name"`
    UserID               string `gorm:"column:User ID"`
    Country              string `gorm:"column:Country"`
    RegistrationDateTime string `gorm:"column:Registration Date & Time"`
    WinCount             int    `gorm:"column:Win Count"`
}

注意:结构体字段必须首字母大写(可导出),否则Gorm无法完成反射赋值。

2. 执行查询并映射结果

方案一:直接复用现有SQL(推荐,无需修改已经验证过的SQL逻辑)

var userWinStats []UserWinStat

querySQL := `
Select CONCAT(kafka_user_stream.FirstName,' ', kafka_user_stream.LastName) AS "Full Name", 
kafka_user_stream.UID AS "User ID", 
kafka_user_stream.CountryCode AS "Country",
kafka_user_stream.CreatedAt AS "Registration Date & Time",
COUNT(jackpotmessage_stream.UID) AS "Win Count"
FROM kafka_user_stream LEFT JOIN 
jackpotmessage_stream ON jackpotmessage_stream.UID = kafka_user_stream.UID
WHERE "Type"='goldenTicketWin' 
GROUP BY "Full Name", "User ID", "Country", "Registration Date & Time"
ORDER BY "Win Count" DESC
`

// 使用Raw执行原生查询,Scan将结果映射到结构体切片
err := s.db.Raw(querySQL).Scan(&userWinStats).Error
if err != nil {
    // 自行处理查询错误逻辑
}

// 后续直接遍历userWinStats即可拿到所有查询结果

方案二:使用Gorm链式API实现(无需硬写完整SQL)

前提是你已经定义了kafka_user_stream表对应的Gorm模型结构体,示例中假设模型名为KafkaUserStream:

var userWinStats []UserWinStat

err := s.db.Model(&KafkaUserStream{}).
    Select(`
        CONCAT(kafka_user_stream.FirstName,' ', kafka_user_stream.LastName) AS "Full Name",
        kafka_user_stream.UID AS "User ID",
        kafka_user_stream.CountryCode AS "Country",
        kafka_user_stream.CreatedAt AS "Registration Date & Time",
        COUNT(jackpotmessage_stream.UID) AS "Win Count"
    `).
    Joins("LEFT JOIN jackpotmessage_stream ON jackpotmessage_stream.UID = kafka_user_stream.UID").
    Where("Type = ?", "goldenTicketWin").
    Group(`"Full Name", "User ID", "Country", "Registration Date & Time"`).
    Order(`"Win Count" DESC`).
    Scan(&userWinStats).Error

if err != nil {
    // 自行处理查询错误逻辑
}
注意事项
  • 不同数据库的标识符引号规则有差异,如果你使用MySQL,上述SQL里的双引号需要替换为反引号,PostgreSQL、SQLite使用双引号即可
  • 若查询结果为空,Scan不会返回错误,只会返回长度为0的切片,需自行判断长度处理空结果场景
  • 如果你需要分页查询,可以在链式调用中追加Offset、Limit方法即可

内容的提问来源于stack exchange,提问作者Haseeb Asjad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 18:09:03