在SQL查询中重复时合并列中的数据

时间:2017-01-03 11:52:39

标签: sql sql-server-2012

我在这里有这个问题:

SELECT flightdata.FLIGHTID,
       flightdata.FLIGHTDATE,
       comments.COMMENT,
       comments.SURVEYID,
       providercodes.PROVIDERNAME
FROM dbo.AnswersComment AS comments
     INNER JOIN dbo.Surveys AS surveys ON comments.SURVEYID = surveys.ID
     INNER JOIN dbo.FlightData AS flightdata ON surveys.FLIGHTDATAID = flightdata.ID
     INNER JOIN dbo.FlightProviderData AS providerdata ON providerdata.FLIGHTDATAID = flightdata.ID
     INNER JOIN dbo.ProviderCode AS providercodes ON providercodes.ID = providerdata.PROVIDERCODEID
ORDER BY FLIGHTDATE ASC;

它产生的数据就像这样:

+--------+------------+--------------+----------+--------------+
| FLIGHT | FLIGHTDATE |   COMMENT    | SUVERYID | PROVIDERNAME |
+--------+------------+--------------+----------+--------------+
| ID0000 | 2016-08-04 | some comment |   123456 | ABC          |
+--------+------------+--------------+----------+--------------+

查询用于获取客户在使用我们的某个航班后留下的评论。当两个调查ID相同时,我想解决的问题就出现了。然后我得到重复的行,其中所有数据都是相同的,除了提供者(因为一个航班一次可以有多个提供者):

+--------+------------+--------------+----------+--------------+
| FLIGHT | FLIGHTDATE |   COMMENT    | SUVERYID | PROVIDERNAME |
+--------+------------+--------------+----------+--------------+
| ID0000 | 2016-08-04 | some comment |   123456 | ABC          |
| ID0000 | 2016-08-04 | some comment |   123456 | CBA          |
+--------+------------+--------------+----------+--------------+

当两个调查ID相同时,我想要发生的是:

+--------+------------+--------------+----------+--------------+
| FLIGHT | FLIGHTDATE |   COMMENT    | SUVERYID | PROVIDERNAME |
+--------+------------+--------------+----------+--------------+
| ID0000 | 2016-08-04 | some comment |   123456 | ABC,CBA      |
+--------+------------+--------------+----------+--------------+

以便在查询期间将提供程序名称合并到一列中,并以逗号分隔。我如何实现这一点,修改我得到的当前查询?

1 个答案:

答案 0 :(得分:1)

聚合字符串连接在SQL Server中很痛苦 - 需要使用带有for xml path的子查询。如果您知道只有2个或3个提供者,则可以使用另一个技巧:

with t as (<your query here>)
select FLIGHT, FLIGHTDATE, COMMENT, SURVEYID,
       (max(case when seqnum = 1 then providername else '' end) +
        max(case when seqnum = 2 then ',' + providername else '' end) +
        max(case when seqnum = 3 then ',' + providername else '' end)
       ) as providernames 
from (select t.*,
             row_number() over (partition by FLIGHT, FLIGHTDATE, COMMENT, SURVEYID order by providername) as seqnum
      from t
     ) t
group by FLIGHT, FLIGHTDATE, COMMENT, SURVERID;