ORM 子查询Subquery是处理复杂 SQL 查询的常见需求。以下是 GORM 中实现子查询的主要方式1. 基础子查询使用*gorm.DB作为条件值GORM 会自动生成子查询go复制// 查询订单金额大于平均订单金额的所有订单 db.Where(amount (?), db.Table(orders).Select(AVG(amount))).Find(orders) // 生成的 SQL: // SELECT * FROM orders WHERE amount (SELECT AVG(amount) FROM orders);2. 使用.QueryExpr()/.SubQuery()显式标记子查询表达式go复制// 查询存在至少一个订单的用户 subQuery : db.Table(orders).Select(user_id).Where(status ?, paid) db.Where(id IN (?), subQuery).Find(users) // 或使用 SubQuery (GORM v2) subQuery : db.Table(orders).Select(user_id).Where(status ?, paid) db.Where(id IN (?), subQuery.SubQuery()).Find(users)3. 关联子查询EXISTSgo复制// 查询有订单的用户 db.Where(EXISTS (?), db.Table(orders).Select(1).Where(orders.user_id users.id)).Find(users) // 生成的 SQL: // SELECT * FROM users WHERE EXISTS ( // SELECT 1 FROM orders WHERE orders.user_id users.id // );4. FROM 子句中的子查询派生表go复制// 查询每个用户的订单总金额并筛选总额大于1000的 subQuery : db.Table(orders).Select(user_id, SUM(amount) as total).Group(user_id) db.Table((?) as u, subQuery).Where(total ?, 1000).Find(results) // 或使用 Table 直接写 SQL db.Table((?) as t, db.Table(orders).Select(*)).Find(results)5. SELECT 中的子查询go复制// 查询用户并附带订单数量 db.Select(*, (?) as order_count, db.Table(orders).Select(COUNT(*)).Where(orders.user_id users.id)).Find(users)6. 使用 Scopes 封装复用go复制func ActiveUsers(db *gorm.DB) *gorm.DB { return db.Where(status ?, active) } // 子查询复用 subQuery : db.Model(User{}).Scopes(ActiveUsers).Select(id) db.Where(user_id IN (?), subQuery).Find(orders)7. 复杂示例多表关联子查询go复制// 查询购买了指定分类商品的用户 subQuery : db.Table(order_items). Select(DISTINCT order_id). Joins(JOIN products ON products.id order_items.product_id). Where(products.category ?, electronics) db.Where(id IN (?), db.Table(orders).Select(user_id).Where(id IN (?), subQuery), ).Find(users)注意事项表格场景说明参数绑定子查询中的参数会自动绑定防止 SQL 注入性能子查询可能性能较差大数据量时考虑 JOIN 或临时表别名派生表FROM 子查询必须指定别名GORM 版本v1 和 v2 的 API 略有差异v2 更推荐使用SubQuery()如果你有具体的业务场景或遇到报错可以提供代码我可以帮你针对性地优化。
gorm subquery
发布时间:2026/5/18 17:42:15
ORM 子查询Subquery是处理复杂 SQL 查询的常见需求。以下是 GORM 中实现子查询的主要方式1. 基础子查询使用*gorm.DB作为条件值GORM 会自动生成子查询go复制// 查询订单金额大于平均订单金额的所有订单 db.Where(amount (?), db.Table(orders).Select(AVG(amount))).Find(orders) // 生成的 SQL: // SELECT * FROM orders WHERE amount (SELECT AVG(amount) FROM orders);2. 使用.QueryExpr()/.SubQuery()显式标记子查询表达式go复制// 查询存在至少一个订单的用户 subQuery : db.Table(orders).Select(user_id).Where(status ?, paid) db.Where(id IN (?), subQuery).Find(users) // 或使用 SubQuery (GORM v2) subQuery : db.Table(orders).Select(user_id).Where(status ?, paid) db.Where(id IN (?), subQuery.SubQuery()).Find(users)3. 关联子查询EXISTSgo复制// 查询有订单的用户 db.Where(EXISTS (?), db.Table(orders).Select(1).Where(orders.user_id users.id)).Find(users) // 生成的 SQL: // SELECT * FROM users WHERE EXISTS ( // SELECT 1 FROM orders WHERE orders.user_id users.id // );4. FROM 子句中的子查询派生表go复制// 查询每个用户的订单总金额并筛选总额大于1000的 subQuery : db.Table(orders).Select(user_id, SUM(amount) as total).Group(user_id) db.Table((?) as u, subQuery).Where(total ?, 1000).Find(results) // 或使用 Table 直接写 SQL db.Table((?) as t, db.Table(orders).Select(*)).Find(results)5. SELECT 中的子查询go复制// 查询用户并附带订单数量 db.Select(*, (?) as order_count, db.Table(orders).Select(COUNT(*)).Where(orders.user_id users.id)).Find(users)6. 使用 Scopes 封装复用go复制func ActiveUsers(db *gorm.DB) *gorm.DB { return db.Where(status ?, active) } // 子查询复用 subQuery : db.Model(User{}).Scopes(ActiveUsers).Select(id) db.Where(user_id IN (?), subQuery).Find(orders)7. 复杂示例多表关联子查询go复制// 查询购买了指定分类商品的用户 subQuery : db.Table(order_items). Select(DISTINCT order_id). Joins(JOIN products ON products.id order_items.product_id). Where(products.category ?, electronics) db.Where(id IN (?), db.Table(orders).Select(user_id).Where(id IN (?), subQuery), ).Find(users)注意事项表格场景说明参数绑定子查询中的参数会自动绑定防止 SQL 注入性能子查询可能性能较差大数据量时考虑 JOIN 或临时表别名派生表FROM 子查询必须指定别名GORM 版本v1 和 v2 的 API 略有差异v2 更推荐使用SubQuery()如果你有具体的业务场景或遇到报错可以提供代码我可以帮你针对性地优化。