SQL Server中基于指定列去重并填充合并列值的方案咨询
基于指定列去重并合并非空列的SQL实现方案
针对你需求的Employee表去重场景,这里提供两种可行的SQL实现方案,分别对应取非空列的有效值和合并所有非空不同值的场景:
1. 使用聚合函数(MAX)提取非空值
利用MAX()函数会忽略空字符串的特性,按指定的去重列分组,对其他列取最大值即可得到非空的有效值。
示例SQL
SELECT FirstName, LastName, Country, MAX(ColumnX) AS ColumnX, MAX(ColumnY) AS ColumnY FROM Employee GROUP BY FirstName, LastName, Country;
结果说明
- 对于
Raj Gupta India的记录,ColumnX会取bb,ColumnY取11; - 对于
James Barry UK的记录,ColumnX取aa,ColumnY取22; - 无有效非空值的记录(如
Mohan Kumar USA)会保留空字符串。
2. 使用STRING_AGG合并所有非空不同值
如果需要将同一列的所有非空不同值拼接起来(比如ColumnX有多个不同非空值时合并),可以用SQL Server 2017及以上版本支持的STRING_AGG()函数,同时过滤空字符串:
示例SQL
SELECT FirstName, LastName, Country, STRING_AGG(NULLIF(ColumnX, ''), ', ') AS ColumnX, STRING_AGG(NULLIF(ColumnY, ''), ', ') AS ColumnY FROM Employee GROUP BY FirstName, LastName, Country;
结果说明
- 若同一分组下某列有多个非空值,会用
,拼接(可自定义分隔符); NULLIF(ColumnX, '')用于将空字符串转为NULL,避免被STRING_AGG包含进去。
适配动态去重列的场景
因为你提到去重依据的列可能由外部用户修改,无法固定写死,可以用动态SQL生成查询逻辑:
示例动态SQL
DECLARE @GroupByColumns NVARCHAR(MAX) = 'FirstName, LastName, Country'; -- 外部传入的分组列 DECLARE @AggregateColumns NVARCHAR(MAX); -- 自动生成其他列的聚合逻辑(这里用MAX为例,可替换为STRING_AGG) SELECT @AggregateColumns = STRING_AGG( CONCAT('MAX(', QUOTENAME(name), ') AS ', QUOTENAME(name)), ', ' ) FROM sys.columns WHERE object_id = OBJECT_ID('Employee') AND name NOT IN (SELECT TRIM(value) FROM STRING_SPLIT(@GroupByColumns, ',')); -- 拼接并执行最终SQL DECLARE @FinalSQL NVARCHAR(MAX) = CONCAT( 'SELECT ', @GroupByColumns, ', ', @AggregateColumns, ' FROM Employee GROUP BY ', @GroupByColumns ); EXEC sp_executesql @FinalSQL;
说明
- 动态获取表中除分组列外的所有字段,自动生成聚合表达式;
- 可以根据需求替换聚合函数(比如把
MAX换成STRING_AGG(NULLIF(...), ', ')); STRING_SPLIT用于拆分外部传入的分组列字符串,需SQL Server 2016+支持。
内容的提问来源于stack exchange,提问作者Sebastian Baranowski
相关产品推荐
相关产品推荐

