SQL FOR XML PATH列表和COUNT

时间:2011-05-20 15:41:29

标签: sql-server for-xml-path

我有一张表如:

|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]

是否有更优雅的查询?

2 个答案:

答案 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标识符和保留字(如DateOrder)作为您自己的列和/或表名....它总是相当混乱。 ...