如果行在其他列中具有相同的数据,则 SQL 查询 CONCAT/列出唯一列数据?
Posted
技术标签:
【中文标题】如果行在其他列中具有相同的数据,则 SQL 查询 CONCAT/列出唯一列数据?【英文标题】:SQL query to CONCAT/list unique column data if rows have identical data in the other columns? 【发布时间】:2021-12-23 16:35:23 【问题描述】:提前致谢。我基本上是在尝试运行 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 我在这里解释了同样的事情:***.com/questions/69895021/… 我可以将它添加到我现有的查询中吗? Anton Grig 在下面做了,但还是不行 我对 STRING_AGG 命令进行了一些研究 - 我的数据库版本不够新,无法使用它(SQL Server 12) 【参考方案1】:如前所述,您应该按如下方式使用 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]
【讨论】:
不幸的是,我得到了:函数“String_Agg”可能没有 WITHIN GROUP 子句。 我对 STRING_AGG 命令进行了一些研究 - 我的数据库版本不够新,无法使用它(SQL Server 12) @S.Hampton 我为您的情况添加了另一个解决方案。 非常感谢! - 我必须做的唯一更改是从 CTE 中删除 ORDER BY 子句:“ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效,除非还指定了 TOP、OFFSET 或 FOR XML 。”以上是关于如果行在其他列中具有相同的数据,则 SQL 查询 CONCAT/列出唯一列数据?的主要内容,如果未能解决你的问题,请参考以下文章