我有一张表如:
|Date |Name|
--------------------
|'20-May-2011'|Bob |
|'20-May-2011'|Fred|
|'20-May-2011'|Jim |
|'21-May-2011'|Bob |
|'21-May-2011'|Ed |
|'22-May-2011'|Bill|
我需要一个返回的查询:
|Date |Count|Names |
--------------------------------------
|'20-May-2011'| 3|'Bob, Fred, Jim'|
|'21-May-2011'| 2|'Bob, Ed' |
|'22-May-2011'| 1|'Bill' |
换句话说,我希望按日期列出名单和计数。 我能想到的最好的是:
SELECT list.[Date], [Count], [Names]
FROM (
SELECT [Date],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH('')
), 1, 2, '') AS [Names]
FROM #table t
GROUP BY [Date]
) [list]
INNER JOIN (
SELECT [Date],
COUNT(*) AS [Count]
FROM #table t
GROUP BY [Date]
) [count]
ON list.[Date] = count.[Date]
ORDER BY [Count] DESC, list.[Date]
是否有更优雅的查询?
答案 0 :(得分:5)
SELECT [Date],
COUNT(*) AS [Count],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH('')
), 1, 2, '') AS [Names]
FROM #table t
GROUP BY [Date]
如果您认为“名称”列可能包含<>'"&
,则应该这样做:
SELECT [Date],
COUNT(*) AS [Count],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH(''), TYPE
).value('.', 'varchar(max)'), 1, 2, '') AS [Names]
FROM #table t
GROUP BY [Date]
答案 1 :(得分:2)
并不是更好 - 但是可能使用单个CTE将XML-PATH填充“封装”成更加可行的方式会起作用吗?
;WITH ConsolidatedData AS
(
SELECT
[Date],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH('')
), 1, 2, '') AS [Names]
FROM #table t
)
SELECT
[Date], Names, COUNT(*)
FROM
ConsolidatedData
GROUP BY
[Date], Names
不确定您是否将此视为一个“复合”声明,或两个....: - )
建议之一:尽量不要使用SQL Server标识符和保留字(如Date
或Order
)作为您自己的列和/或表名....它总是相当混乱。 ...