GORM 子查询实现
本文介绍 GORM 中子查询的构建方式及其在复杂查询中的应用。
SubQuery 方法
基本用法
将子查询结果作为条件或字段嵌入主查询。
Go
// 子查询作为字段
subQuery := db.Table("orders").Select("AVG(amount)").Where("user_id = users.id")
db.Model(&User{}).Select("*, (?) AS avg_order", subQuery).Find(&users)
// 子查询作为条件
subQuery := db.Table("orders").Select("user_id").Where("amount > ?", 100)
db.Where("id IN (?)", subQuery).Find(&users)
语法格式:
Go
subQuery := db.Table("表名").Select("字段").Where("条件")
db.Where("字段 IN (?)", subQuery).Find(&results)
WHERE 子句中的子查询
Go
// IN 子查询
subQuery := db.Table("orders").Select("user_id").Where("status = ?", "completed")
db.Where("id IN (?)", subQuery).Find(&users)
// NOT IN 子查询
subQuery := db.Table("banned_users").Select("user_id")
db.Where("id NOT IN (?)", subQuery).Find(&users)
// EXISTS 子查询
subQuery := db.Table("orders").Select("1").Where("user_id = users.id AND amount > ?", 500)
db.Where("EXISTS (?)", subQuery).Find(&users)
SELECT 子句中的子查询
Go
// 标量子查询作为字段
orderCount := db.Table("orders").Select("COUNT(*)").Where("user_id = users.id")
db.Model(&User{}).Select("*, (?) AS order_count", orderCount).Find(&users)
avgAmount := db.Table("orders").Select("AVG(amount)").Where("user_id = users.id")
db.Model(&User{}).Select("*, (?) AS avg_amount", avgAmount).Find(&users)
FROM 子句中的子查询
Go
// 子查询作为派生表
subQuery := db.Table("orders").Select("user_id, SUM(amount) as total").Group("user_id")
db.Table("(?) AS u", subQuery).Find(&results)
// 复杂嵌套
subQuery := db.Table("orders").Select("user_id, COUNT(*) as cnt").Group("user_id").Where("cnt > ?", 5)
db.Table("(?) AS frequent_buyers", subQuery).Joins("JOIN users ON users.id = frequent_buyers.user_id").Find(&users)
嵌套子查询
Go
// 多层嵌套
innerQuery := db.Table("order_items").Select("order_id").Where("price > ?", 100)
middleQuery := db.Table("orders").Select("user_id").Where("id IN (?)", innerQuery)
db.Where("id IN (?)", middleQuery).Find(&users)
注意事项
- 子查询中
?占位符自动包裹括号,无需手动添加()。- 作为字段的标量子查询需确保只返回单个值,否则可能报错。
- 深层嵌套子查询可读性差,可考虑使用临时表或分步查询替代。
- 子查询性能不如 JOIN 时,优先评估数据量和索引情况。
要点总结
- SubQuery 方法返回
*gorm.SubQuery类型,可直接嵌入主查询。 - WHERE 子查询常用 IN/NOT IN/EXISTS 语法实现条件过滤。
- SELECT 子查询用于添加计算字段。
- FROM 子查询将子查询结果作为临时表使用。
- 子查询嵌套层数过多时,考虑使用 JOIN 或分步查询优化可读性与性能。
存放路径:D:\git2\jwdev\articles\GORM\进阶\高级查询技术\子查询实现.md
📝 发现内容有误?点击此处直接编辑