Beego ORM 不支持 DISTINCT,需用 Raw() 手写 SELECT DISTINCT 实现去重;ValuesList 仅提取字段不实现去重;Raw() 不支持链式 Filter(),条件须内嵌 SQL 并用占位符传参。

Beego ORM 本身不支持 DISTINCT
Beego 的 QuerySeter(比如 QueryTable("user").Filter(...))没有提供 .Distinct() 或类似方法。你调用 All()、Values() 等,返回的都是原始 SQL 的全量结果,不会自动去重。
必须用 Raw() 手写 SELECT DISTINCT
要拿到去重后的唯一值,只能退到原生 SQL 层,用 Raw() 显式写 DISTINCT。常见场景有两类:
- 查单个字段的唯一值(如所有不重复的
status):o.Raw("SELECT DISTINCT status FROM user").Values(&list) - 查多个字段组合的唯一行(如唯一
(city, district)对):o.Raw("SELECT DISTINCT city, district FROM address").Values(&list)
注意:不能混用 Raw() 和 Filter() 链式调用——Raw() 是独立执行路径,不接受 ORM 条件拼接。条件得直接写进 SQL 字符串里,用占位符传参,例如:o.Raw("SELECT DISTINCT name FROM user WHERE age > ?", minAge).Values(&names)。
ValuesList 不能替代 DISTINCT
有人误以为 ValuesList(&list, "name") 能去重,其实它只是提取指定字段并转成扁平切片([][]interface{}),和 DISTINCT 完全无关。哪怕数据库里有 100 条 name="admin",ValuesList 仍会返回 100 个 "admin"。
去重逻辑放在 Go 层是下策
除非数据量极小(All() 全查出来,再用 map[string]struct{} 去重。这既浪费内存又拖慢响应——数据库本就能高效完成的事,不该推给应用层。
真正容易被忽略的是:DISTINCT 对 NULL 值的处理。MySQL 中 SELECT DISTINCT col FROM t 会把所有 NULL 当作一个值返回(即最多一个 NULL),但如果你在 WHERE 中用了 col IS NULL,得确认业务是否真需要这个语义。别默认以为“去重=删掉重复”,而忘了 NULL 的特殊性。











