按唯一ID计数,分组

时间:2014-07-18 16:57:38

标签: sql sql-server reporting-services sql-server-2008-r2

我继承了一些按部门统计团队人数的脚本;当前脚本为每个单独的部门创建一个表,而以前的用户将数据复制/粘贴到Excel中。我的任务是将此报告提取到SSRS中,因此我需要按团队为所有部门提供一个表格。

当前表格

+-------+-----------+---------+
| Dept  | DataMatch |  Team   |
+-------+-----------+---------+
|    01 | 4687Joe   | Dodgers |
|    01 | 3498Cindy | RedSox  |
|    01 | 1057Bob   | Yankees |
|    01 | 0497Lucy  | Dodgers |
|    02 | 7934Jean  | Yankees |
|    02 | 4584Tom   | Dodgers |
+-------+-----------+---------+

期望的结果

+-------+---------+--------+---------+
| Dept  | Dodgers | RedSox | Yankees |
+-------+---------+--------+---------+
|    01 |       2 |      1 |       1 |
|    02 |       1 |      0 |       1 |
+-------+---------+--------+---------+

DataMatch字段是我将要计算的唯一标识符。我开始将每个部门包装在一个CTE中但是这会导致部门不适用于我的报告,所以我需要调整我的结果并且我还没有能够解决这个问题。有60个部门,我的查询变得很长。

当前查询

SELECT Dept, DataMatch, Team INTO #temp_Team
FROM TeamDatabase
WHERE Status = 14
    AND Team <> 'Missing'   
;WITH A_cte (Team, Dept01) 
AS
    (
    SELECT Team
        , COUNT(DISTINCT datamatch) AS 'Dept01' 
    FROM #temp_Team
    WHERE Dept = '01'
    GROUP BY Team
    ), 
B_cte (Team, Dept02) AS 
    (
    SELECT Team
        , COUNT(DISTINCT datamatch) AS 'Dept02' 
    FROM #temp_Team
    WHERE Dept = '02'
    GROUP BY Team
    )
SELECT A_cte.Team
    , A_cte.Dept01
    , B_cte.Dept02
FROM A_cte
INNER JOIN B_cte
    ON A_cte.Team=B_cte.Team

导致:

+----------------------------+-------+-------+
|            Team            | Prg01 | Prg02 |
+----------------------------+-------+-------+
| RedSox                     |   144 |   141 |
| Yankees                    |    63 |   236 |
| Dodgers                    |   298 |   196 |
+----------------------------+-------+-------+

我觉得在我已经很长时间的查询中使用一个数据透视表会过度影响性能,60个部门的行数超过30,000。

我错过了什么,最常见的基本步骤?

TL; DR - 我如何按团队统计人数并按部门列出?

2 个答案:

答案 0 :(得分:1)

我会用动态数据库替换整个查询,而不是向CTE添加数据透视。

您可以将状态/团队条件添加到底部动态查询中的SELECT。它们是WHERE STATUS=14 AND TEAM !=''MISSING'' - 注意这是两个单引号将它嵌套在字符串中。

IF OBJECT_ID('tempdb..#data') IS NOT NULL DROP TABLE #data
CREATE TABLE #data (Dept VARCHAR(50), DataMatch NVARCHAR(50), Team VARCHAR(50))

INSERT INTO #data (Dept, DataMatch, Team) 
VALUES ('01', '4687Joe','Dodgers'), 
       ('01', '3498Cindy','RedSox'),
       ('01', '1057Bob','Yankees'),
       ('01', '0497Lucy','Dodgers'),
       ('02', '7934Jean','Yankees'),
       ('02', '4584Tom','Dodgers')


DECLARE @cols AS NVARCHAR(MAX), 
        @sql  AS NVARCHAR(MAX)

SET @cols = STUFF(
(SELECT N',' + QUOTENAME(y) AS [text()]
FROM (SELECT DISTINCT Team AS y FROM #data) AS Y
ORDER BY y
FOR XML PATH('')),
1, 1, N'');        

SET @sql = 'SELECT Dept, '+@cols+'
            FROM (SELECT Dept, DataMatch, Team
                  FROM #data D) SUB
            PIVOT (COUNT([DataMatch]) FOR Team IN ('+@cols+')) AS P'
PRINT @SQL
EXEC (@SQL)

如果您不想使用动态数据透视表,此处只是一个独立查询...再次根据您的需要添加条件。

SELECT Dept, Dodgers, RedSox, Yankees
FROM (SELECT Dept, DataMatch, Team
      FROM #data D) SUB
PIVOT (COUNT([DataMatch]) FOR Team IN ([Dodgers], [RedSox], [Yankees])) AS P

答案 1 :(得分:0)

我不确定我是否遵循了您现有查询的相关性,但是从当前表格到您想要的结果是PIVOT非常简单的用法:

SELECT *
FROM Table1
PIVOT(COUNT(DataMatch) FOR Team IN (Dodgers,RedSox,Yankees))pvt

演示:SQL Fiddle

如果团队列表不是静态的,那么这当然可以动态完成。