SQL:将重复列值替换为空值的实现方案
实现重复列值置空的报表式查询
问题场景
你有这样一张数据表:
| Company | Date | Paper | Condition |
|---|---|---|---|
| Company1 | 19-12-2007 | PaperA | Release Second Term |
| Company1 | 19-12-2007 | PaperA | Add Third Term |
| Company1 | 19-12-2007 | PaperA | Append First Term |
想要把重复的Company、Date、Paper列值替换为空,得到类似报表合并单元格的效果:
| Company | Date | Paper | Condition |
|---|---|---|---|
| Company1 | 19-12-2007 | PaperA | Release Second Term |
| Add Third Term | |||
| Append First Term |
之前用DISTINCT没达到效果?太正常了——DISTINCT是用来去重整行数据的,根本不是干这个活的~下面给你几种不同数据库环境下的实现方法:
方法1:用窗口函数(推荐,适用于MySQL 8+、SQL Server、PostgreSQL等)
现在大部分主流数据库都支持窗口函数,用ROW_NUMBER()给每组相同的Company、Date、Paper编号,然后只保留每组第一行的原值,其他行置为空即可:
SELECT -- 只有组内第一行显示原值,其余为空 CASE WHEN rn = 1 THEN Company ELSE '' END AS Company, CASE WHEN rn = 1 THEN Date ELSE '' END AS Date, CASE WHEN rn = 1 THEN Paper ELSE '' END AS Paper, Condition FROM ( -- 子查询给每组数据编号 SELECT *, ROW_NUMBER() OVER ( PARTITION BY Company, Date, Paper -- 按这三列分组 ORDER BY Condition -- 组内排序,确定哪行是第一行 ) AS rn FROM your_table_name -- 替换成你的表名 ) t -- 保持排序一致,避免结果混乱 ORDER BY Company, Date, Paper, rn;
如果你想指定组内第一行是特定的记录,调整ORDER BY后面的字段就行,比如按Condition的业务逻辑排序。
方法2:MySQL 5.x及以下版本(无窗口函数)
旧版MySQL没有窗口函数,我们可以用用户变量来记录上一行的值,实现相同效果:
SELECT CASE WHEN @prev_company = Company THEN '' ELSE @prev_company := Company END AS Company, CASE WHEN @prev_date = Date THEN '' ELSE @prev_date := Date END AS Date, CASE WHEN @prev_paper = Paper THEN '' ELSE @prev_paper := Paper END AS Paper, Condition FROM your_table_name, -- 初始化变量为空字符串 (SELECT @prev_company := '', @prev_date := '', @prev_paper := '') vars -- 必须按分组列排序,不然变量记录会出错 ORDER BY Company, Date, Paper, Condition;
⚠️ 注意:这种写法一定要加上ORDER BY,保证相同分组的行连续出现,否则变量的判断会混乱。
小提醒
这种处理只是在查询结果中做展示用,千万不要直接修改原表把重复值改成空值!原表保留完整数据才是正确的做法,空值会丢失原始信息,后续统计或查询都会出问题。
内容的提问来源于stack exchange,提问作者Karen
相关产品推荐
相关产品推荐

