如果行在其他列中具有相同数据,SQL 查询 CONCAT/list 唯一列数据?

SQL query to CONCAT/list unique column data if rows have identical data in the other columns?

提前致谢。我基本上是在尝试 运行 一个 SQL 查询,以便 StaffID:Name:Floor:Date:Shifts 的结果是 1:1:1:1:Many。

这是我的初始查询和示例结果:

SELECT
    ST.STAFFNUM [StaffID],
    ST.FULLNAME [Name],
    ST.AREA [Floor],
    CONVERT(VARCHAR(10), TS.EVENTDATE, 103) [Date],
    LEFT(CONVERT(VARCHAR(10), TS.SHIFTSTART, 8), 5) [ShiftStart],
    LEFT(CONVERT(VARCHAR(10), TS.SHIFTEND, 8), 5) [ShiftEnd]
FROM
    TIMES TS
    LEFT JOIN STAFF ST ON TS.STAFFNUM = ST.STAFFNUM
WHERE
        TS.EVENTDATE BETWEEN '2021/01/01' AND '2021/01/01'
ORDER BY
    ST.AREA,
    ST.FULLNAME,
    TS.EVENTDATE,
    TS.SHIFTSTART
;

StaffID | Name    | Floor | Date       | ShiftStart | ShiftEnd
==============================================================
1000    | Andrew  | 1     | 01/01/2021 | 06:00      | 14:00
1000    | Andrew  | 1     | 01/01/2021 | 14:00      | 15:00
8654    | Belinda | 2     | 01/01/2021 | 06:00      | 14:00
9876    | Craig   | 3     | 01/01/2021 | 06:00      | 14:00

然后我将 ShiftStart 和 ShiftEnd 列与以下内容结合起来,得到以下结果:

CONCAT(LEFT(CONVERT(VARCHAR(10), TS.SHIFTSTART, 8), 5),'-',LEFT(CONVERT(VARCHAR(10), TS.SHIFTEND, 8), 5)) [Shift]

StaffID | Name    | Floor | Date       | Shift
====================================================
1000    | Andrew  | 1     | 01/01/2021 | 06:00-14:00
1000    | Andrew  | 1     | 01/01/2021 | 14:00-15:00
8654    | Belinda | 2     | 01/01/2021 | 06:00-14:00
9876    | Craig   | 3     | 01/01/2021 | 06:00-14:00

我想不出接下来要做的是将 Andrew 的班次(以及其他任何人在同一日期和楼层等的多个班次)组合起来,如下所示:

StaffID | Name    | Floor | Date       | Shifts
=================================================================
1000    | Andrew  | 1     | 01/01/2021 | 06:00-14:00, 14:00-15:00
8654    | Belinda | 2     | 01/01/2021 | 06:00-14:00
9876    | Craig   | 3     | 01/01/2021 | 06:00-14:00

注意:如果某人被转移到另一个楼层(偶尔),我想将 Shift/s 保留在该楼层独有的单独行中,以便可以拆分楼层数据并通过电子邮件发送给该楼层的经理。 只要行的所有数据都相同,除了 Shift,我想合并这些行并列出 Shifts。 再次感谢!

如上所述,您应该按如下方式使用 String_Agg 函数:

SELECT [StaffID], Max([Name]) As Name, [Floor], [Date], String_Agg([Shift], ',') WITHIN GROUP (ORDER BY [Shift]) As Shifts
FROM (
SELECT
    ST.STAFFNUM [StaffID],
    ST.FULLNAME [Name],
    ST.AREA [Floor],
    CONVERT(VARCHAR(10), TS.EVENTDATE, 103) [Date],
    CONCAT(LEFT(CONVERT(VARCHAR(10), TS.SHIFTSTART, 8), 5),'-',LEFT(CONVERT(VARCHAR(10), TS.SHIFTEND, 8), 5)) [Shift]
FROM
    TIMES TS
    LEFT JOIN STAFF ST ON TS.STAFFNUM = ST.STAFFNUM
WHERE
        TS.EVENTDATE BETWEEN '2021/01/01' AND '2021/01/01'
ORDER BY
    ST.AREA,
    ST.FULLNAME,
    TS.EVENTDATE,
    TS.SHIFTSTART) As T
Group by [StaffID], [Floor], [Date]

对于 Sql Server 2012,您可以尝试使用“CTE”和“FOR XML PATH”。

WITH CTE As
(SELECT
    ST.STAFFNUM [StaffID],
    ST.FULLNAME [Name],
    ST.AREA [Floor],
    CONVERT(VARCHAR(10), TS.EVENTDATE, 103) [Date],
    CONCAT(LEFT(CONVERT(VARCHAR(10), TS.SHIFTSTART, 8), 5),'-',LEFT(CONVERT(VARCHAR(10), TS.SHIFTEND, 8), 5)) [Shift]
FROM
    TIMES TS
    LEFT JOIN STAFF ST ON TS.STAFFNUM = ST.STAFFNUM
WHERE
        TS.EVENTDATE BETWEEN '2021/01/01' AND '2021/01/01'
ORDER BY
    ST.AREA,
    ST.FULLNAME,
    TS.EVENTDATE,
    TS.SHIFTSTART)
SELECT [StaffID], MAX([Name]) AS [Name], [Floor], [Date], 
       STUFF((SELECT ', ' + [Shift]  
              FROM CTE
              WHERE [StaffID] = T.[StaffID] AND [Floor] = T.[Floor] AND [Date] = T.[Date]
              FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)'),1,1,'') AS Shifts              
FROM CTE AS T
GROUP BY [StaffID], [Floor], [Date]