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

GORM(Golang)中如何实现带Where、Order By的多表Union查询

问题原因

原有写法不生效的核心逻辑:GORM 不会自动将? UNION ?拼接后的整体结果包装为派生表,后续链式调用的Where、Order方法无法识别Raw语句内的UNION结构,这部分筛选、排序条件会被直接丢弃,不会拼接到最终执行的SQL中。
要实现对UNION合并后结果集的过滤、排序,必须把UNION查询整体作为子查询,在外层包裹查询语句执行条件筛选。

可直接运行的实现方案

方案1:通用兼容方案(所有GORM v2版本可用)

先分别构建两个单表的查询语句,将拼接好的UNION语句作为派生表,在外层执行后续的过滤、排序逻辑:

var union []map[string]interface{}
// 构建两个分支的子查询,不要提前执行Scan
q1 := database.CONNECTION.Select(ContentAttributes).Model(&model1{})
q2 := database.CONNECTION.Select(ContentAttributes).Model(&model2{})
// 将UNION结果作为临时表,外层追加查询条件
database.CONNECTION.Table("(?) AS union_temp",
    database.CONNECTION.Raw("? UNION ?", q1, q2),
).Where("id > ?", 1).Order("name").Scan(&union)

该写法生成的SQL结构完全符合预期:

SELECT * FROM (
    SELECT "id","name","created_at","updated_at" FROM "model1" WHERE "model1"."deleted_at" IS NULL
    UNION
    SELECT "id","name","created_at","updated_at" FROM "model2" WHERE "model2"."deleted_at" IS NULL
) AS union_temp WHERE id > 1 ORDER BY name

方案2:高版本GORM简化写法(v1.23.0及以上版本支持)

如果项目使用的GORM版本较新,可以直接用内置的Union方法构建组合查询,写法更简洁:

var union []map[string]interface{}
// 用内置API构建UNION组合查询
unionQuery := database.CONNECTION.Select(ContentAttributes).Model(&model1{}).
    Union(database.CONNECTION.Select(ContentAttributes).Model(&model2{}))
// 基于UNION结果追加筛选、排序逻辑
database.CONNECTION.Table("(?) AS t", unionQuery).
    Where("id > ?", 1).
    Order("name").
    Scan(&union)
注意事项
  • 参与UNION的两个分支查询,返回字段的数量、顺序、对应字段类型必须完全一致,否则会触发SQL语法错误
  • 如果不需要对合并结果去重,将UNION替换为UNION ALL即可,查询性能会有明显提升
  • 排序如果需要指定升降序,可以直接写为Order("name desc")、Order("id asc")这类标准SQL格式

内容的提问来源于stack exchange,提问作者Rajesh Paul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:57:20