SQL Server将三个不同的列连接到一个逗号中,逗号之间没有重复的值
下表是我在SQL Server中遇到的问题的简化:SQL Server将三个不同的列连接到一个逗号中,逗号之间没有重复的值,sql,sql-server,group-by,string-aggregation,string-agg,Sql,Sql Server,Group By,String Aggregation,String Agg,下表是我在SQL Server中遇到的问题的简化: ID COLUMN_A COLUMN_B COLUMN_C ------------------------------------- 1 A B C 1 A B D 1 B C D 我想得到一个组,其中的列由逗号连接,没有重复的值。我尝试使用字符串_AGG(),但它返回: ID CO
ID COLUMN_A COLUMN_B COLUMN_C
-------------------------------------
1 A B C
1 A B D
1 B C D
我想得到一个组,其中的列由逗号连接,没有重复的值。我尝试使用字符串_AGG(),但它返回:
ID COLUMN_A COLUMN_B COLUMN_C
-------------------------------------
1 A, A, B B, B, C C, D, D
这是我所做的查询:
SELECT ID, STRING_AGG(COLUMN_A, ', ') AS COL_A, STRING_AGG(COLUMN_B, ', ') AS COL_B,
STRING_AGG(COLUMN_C, ', ') AS COL_C
FROM MYTABLE
GROUP BY ID;
我想知道下一个结果:
ID COLUMN_A COLUMN_B COLUMN_C
-------------------------------------
1 A, B B, C C, D
谢谢大家! 不幸的是,
string\u agg(distinct)
还不能工作。但你可以做一些更复杂的事情:
SELECT ID,
STRING_AGG(CASE WHEN seqnum_a = 1 THEN COLUMN_A, END ', ') AS COLUMN_A,
STRING_AGG(CASE WHEN seqnum_b = 1 THEN COLUMN_B, END ', ') AS COLUMN_B,
STRING_AGG(CASE WHEN seqnum_c = 1 THEN COLUMN_C, END ', ') AS COLUMN_C
FROM (SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY ID, COLUMN_A ORDER BY ID) as seqnum_a,
ROW_NUMBER() OVER (PARTITION BY ID, COLUMN_B ORDER BY ID) as seqnum_b,
ROW_NUMBER() OVER (PARTITION BY ID, COLUMN_C ORDER BY ID) as seqnum_c
FROM MYTABLE t
) t
GROUP BY ID;
因此,尽管
STRING\u AGG()
不会删除重复项,但它会忽略NULL
值。以下是基于XML和XQuery的解决方案
SQL
不使用
窗口功能
。union
可能会减慢速度,但请尝试一下,看看您是否能容忍这种性能
with
cte1 (id, col, indicator) as
(select id, column_a, 'col1' from t union
select id, column_b, 'col2' from t union
select id, column_c, 'col3' from t),
cte2 (id, indicator, agg) as
(select id, indicator, string_agg(col,',')
from cte1
group by id, indicator)
select id,
max(case when indicator='col1' then agg end) as column_a,
max(case when indicator='col2' then agg end) as column_b,
max(case when indicator='col3' then agg end) as column_c
from cte2
group by id;
谢谢你的快速回答。它抛出了下一个错误,函数ROW_NUMBER必须有一个带有orderby的OVER子句。我不知道它是如何工作的,但工作得很完美。如果您能解释一下功能,那将非常有帮助。多谢各位@alejoaldana我们首先以一种允许我们重复数据并指示每个堆栈指示的列的方式来堆叠数据集。然后,您只需将它们聚合。case语句就在那里,因此您可以有三个以指示符为条件的列。在这个演示中,我已经将这个代码分成了几部分,所以您可以理解它是如何工作的。非常感谢!真的很有帮助!
+----+-------+-------+-------+
| ID | COL_A | COL_B | COL_C |
+----+-------+-------+-------+
| 1 | A, B | B, C | C, D |
+----+-------+-------+-------+
with
cte1 (id, col, indicator) as
(select id, column_a, 'col1' from t union
select id, column_b, 'col2' from t union
select id, column_c, 'col3' from t),
cte2 (id, indicator, agg) as
(select id, indicator, string_agg(col,',')
from cte1
group by id, indicator)
select id,
max(case when indicator='col1' then agg end) as column_a,
max(case when indicator='col2' then agg end) as column_b,
max(case when indicator='col3' then agg end) as column_c
from cte2
group by id;