SQL使用DISTINCT时含CASE条件生成字段出现重复记录如何解决
问题原因
你的核心问题是DISTINCT会对所有返回列做唯一性判定,你生成的标识列col也被纳入了去重判断:同一组(f1,f2)下如果同时存在匹配参数、不匹配参数的记录,就会因为col值分别为1和0被判定为两条独立记录,产生你看到的重复数据。
你之前写的嵌套子查询+外层GROUP BY报错/结果不对,本质是违反了SQL分组语法规则:SELECT列表中的非分组字段必须套聚合函数,你要么没给col加聚合直接查,要么把col也放进了分组字段,自然要么报错要么和原DISTINCT效果一致。
正确解决方案
直接去掉冗余的DISTINCT,按你需要保留唯一性的业务字段(也就是除了标识列之外的所有返回字段)做分组,对标识列用MAX()聚合即可,完全满足需求:
- 只要分组内存在任意一条匹配
@param的记录,MAX()就会取到1作为标识值 - 如果分组内所有记录都不匹配参数,
MAX()返回0 - 分组本身就会实现「非标识列相同只留一条记录」的去重效果,替代原来的
DISTINCT作用
参考代码如下:
SELECT t.[f1], t.[f2], -- 此处按顺序放你需要返回的其他非标识字段 CAST(MAX(CASE WHEN t.MyField = @param THEN 1 ELSE 0 END) AS BIT) AS col FROM [你的表名] t -- 原来的WHERE筛选条件直接保留在这里即可 GROUP BY t.[f1], t.[f2] -- 此处和SELECT列表的非标识字段一一对应即可
效果验证
针对你给出的测试数据,聚合逻辑的计算结果如下:
| f1 | f2 | 分组内原始col值 | MAX聚合后col值 |
|---|---|---|---|
| FOO | BAR | 0 | 0 |
| FOO | CAR | 0 | 0 |
| GOO | BAR | 1、0 | 1 |
最终返回结果和你的预期完全一致。
如果你的标识列不需要严格返回BIT类型,可以去掉外层的
CAST函数,写法更简洁。
内容的提问来源于stack exchange,提问作者Aurelio Brunod
相关产品推荐
相关产品推荐

