T-SQL:每行汇总一个“集合”,然后将它们“联合”起来

时间:2019-06-04 23:09:35

标签: sql-server tsql

我必须“从概念上”写这个问题,因为我不确定实际采用哪种方法。我的提问方式可能会解决XY问题-如果您看到其他建议,请提出其他建议。

我正在对已经投入生产的数据库编写报告查询。考虑下表(类似于我当前的结果集):

Id     | Code1    | Code2    | Code3    |  Code4   | Code5
-----------------------------------------------------------
1        1          2          3           4         5
1        2          3          4           5         6
2        1          null       null        null      null

所有代码在字面上(作为数据类型)和概念上(例如,对于相同类型的事件等,都表示相同的“种类”)都是相同的“类型”。显然,这些数据没有正确归一化,但是我仍然需要对其进行转换。

我想编写一个查询,对ID进行“分组”,并返回5个代码列中所有唯一代码的集合。

最终,我的目标是将表格转换为:

Id      Codes
1       [1, 2, 3, 4, 5, 6]
2       [1]

[]至少在概念上表示某种集合,表或列表类型)

(实际上,我需要结合这些代码进行快速查找,因此“实际”结果应如下所示)

Id      CodeStrings
1       [Foo, Bar, Baz, Bon, Fizz, Buzz]
2       [Foo]

您能描述一个模式,让我每行形成一个“集合”并进行汇总吗?

3 个答案:

答案 0 :(得分:1)

我先取消数据透视表,然后使用For xml path连接按ID分组的行。

答案 1 :(得分:1)

您需要取消透视和重新聚合。在SQL Server 2017+中,这非常简单:

select t.id, string_agg(c.code, ',')
from t cross apply
     (select distinct v.code
      from (values (code1), (code2), (code3), (code4), (code5)
           ) v(code)
      where v.code is not null
     ) c;

在早期版本中,您可以使用for xml path

select t.id, stuff(c.codes, 1, 1, '') as codes
from t cross apply
     (select distinct ',' + v.code
      from (values (code1), (code2), (code3), (code4), (code5)
           ) v(code)
      where v.code is not null
      for xml path ('')
     ) c(codes)

答案 2 :(得分:0)

仅5个,最简单的选择可能是:

Select ID, '[' + ISNULL(Code1, '') 
               + ISNULL(' ,' + Code2, '') 
               + ISNULL(' ,' + Code3, '') 
               + ISNULL(' ,' + Code4, '') 
               + ISNULL(' ,' + Code5, '') + ']'
From MyTable

请注意,如果代码以数字形式存储,则可能需要将代码用castconvert包装到varchar中。