将数据库中的多列合并为一列?

时间:2019-10-22 09:15:14

标签: sql sql-server

我编写了以下SQL查询:

SELECT DISTINCT i.IncidentReference Reference, s.Name Site, it.Description IncidentTypes
    , i.Description, FORMAT(i.CreatedOn,'d MMM yyyy', 'en-US' ) Logged 
FROM Incident i 
INNER JOIN TEST_USWM_TestAutomation.TEST_USWM.uvw_AvailaibleSites s ON i.SiteId = s.Id 
JOIN IncidentIncidentType iit ON i.Id = iit.IncidentId 
JOIN IncidentType it ON iit.IncidentTypeId = it.Id 
JOIN IncidentStatus ins ON i.IncidentStatusId = ins.Id 
WHERE s.Id = 1 /*:siteId */
AND ins.Name = 'Logged' 
AND i.CreatedOn BETWEEN DATEADD(DAY, -30, GETUTCDATE()) AND GETUTCDATE()

哪个返回以下结果:

Reference  Site  IncidentTypes                 Description    Logged
7032       0110  Refrigeration Outage          njfdgdf        25 Sep 2019
7095       0110  Fire/False Evacuation         testing        2 Oct 2019
7096       0110  Fire/False Evacuation         testing        2 Oct 2019
7097       0110  Fire/False Evacuation         test           2 Oct 2019
7097       0110  Flood                         test           2 Oct 2019
7097       0110  Gas Leak/Suspected Gas Leak   test           2 Oct 2019
7098       0110  Flood                         testing        2 Oct 2019
7168       0110  Fire/False Evacuation         test           7 Oct 2019
7330       0110  Refrigeration Outage          Test           15 Oct 2019

但是,我希望将具有相同引用的所有行合并为一行。因此,例如,对于参考-7097,我希望看到IncidentTypes列看起来像-气体泄漏/可疑气体泄漏,火灾/虚假疏散,洪水

什么是最好的方法?

编辑:我已经尝试了@GMB在下面发布的查询,但遇到了错误-函数'STRING_AGG'可能没有WITHIN GROUP子句。这似乎与我使用的SQL Server版本有关。是否有另一种方法可以解决此问题而无需升级版本?

编辑:@Gordon Linoff查询的输出-

3 个答案:

答案 0 :(得分:1)

在MySql中,您可以使用group_concat(it.Description),然后按引用进行分组

SELECT DISTINCT i.IncidentReference Reference, s.Name Site, group_concat(it.Description) IncidentTypes, 
i.Description, FORMAT(i.CreatedOn,'d MMM yyyy', 'en-US' ) Logged 
FROM Incident i 
INNER JOIN TEST_USWM_TestAutomation.TEST_USWM.uvw_AvailaibleSites s ON i.SiteId = s.Id 
JOIN IncidentIncidentType iit ON i.Id = iit.IncidentId 
JOIN IncidentType it ON iit.IncidentTypeId = it.Id 
JOIN IncidentStatus ins ON i.IncidentStatusId = ins.Id 
WHERE s.Id = 1 /*:siteId */
AND ins.Name = 'Logged' 
AND i.CreatedOn BETWEEN DATEADD(DAY, -30, GETUTCDATE()) AND GETUTCDATE() Group by reference;

答案 1 :(得分:1)

在旧版SQL Server中,您可以使用:

SELECT i.IncidentReference as Reference, 
       s.Name as Site, 
       STUFF( (SELECT it.Description + ','
               FROM IncidentType it
               WHERE iit.IncidentTypeId = it.Id 
               ORDER BY it.Description
               FOR XML PATH ('')
              ), 1, 2, ''
             ) as IncidentTypes,
      i.Description,
      FORMAT(i.CreatedOn,'d MMM yyyy', 'en-US' ) as Logged 
FROM Incident i JOIN
     TEST_USWM_TestAutomation.TEST_USWM.uvw_AvailaibleSites s 
     ON i.SiteId = s.Id JOIN
     IncidentStatus ins
     ON i.IncidentStatusId = ins.Id 
WHERE s.Id = 1 /*:siteId */ AND
      ins.Name = 'Logged' AND
      i.CreatedOn BETWEEN DATEADD(DAY, -30, GETUTCDATE()) AND GETUTCDATE();

我认为不需要外部GROUP BY

答案 2 :(得分:0)

您需要使用聚合。

使用GETUTCDATE()往往表明您正在使用SQL Server。在此RDBMS中,可以使用函数STRING_AGG()来汇总描述,如下所示:

SELECT 
    i.IncidentReference Reference, 
    s.Name Site, 
    STRING_AGG(i.Description, ',') WITHIN GROUP(ORDER BY i.Description) IncidentTypes,
    i.Description,
    FORMAT(i.CreatedOn,'d MMM yyyy', 'en-US' ) Logged 
FROM 
    Incident i 
    JOIN TEST_USWM_TestAutomation.TEST_USWM.uvw_AvailaibleSites s ON i.SiteId = s.Id 
    JOIN IncidentIncidentType iit ON i.Id = iit.IncidentId 
    JOIN IncidentType it ON iit.IncidentTypeId = it.Id 
    JOIN IncidentStatus ins ON i.IncidentStatusId = ins.Id 
WHERE 
    s.Id = 1 /*:siteId */
    AND ins.Name = 'Logged' 
    AND i.CreatedOn BETWEEN DATEADD(DAY, -30, GETUTCDATE()) AND GETUTCDATE()
GROUP BY
    i.IncidentReference Reference, 
    s.Name Site, 
    i.Description,
    FORMAT(i.CreatedOn,'d MMM yyyy', 'en-US' ) Logged