【问题标题】:Count by unique ID, group by another按唯一 ID 计数,按另一个分组
【发布时间】:2014-07-18 16:57:38
【问题描述】:

我继承了一些按部门统计团队人数的脚本;当前脚本为每个单独的部门创建一个表格,之前的用户会将数据复制/粘贴到 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 中,但是这导致 Dept 作为列,这不适用于我的报告,因此我需要转置我的结果,但我无法弄清楚。有 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 - 我如何按团队统计人数并按部门列出?

【问题讨论】:

  • 您为什么要事先格式化此数据集?只需将其用作报告的源并实际使用 SSRS 中的工具来获得您想要的结果(这就是 tablix 的用途)

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


【解决方案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

【讨论】:

    【解决方案2】:

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

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

    演示:SQL Fiddle

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

    【讨论】:

    • 这导致每个人的一行在正确的列中都有一个“1”。
    • @silviak 您问题中的示例表与实际表格式不匹配吗?链接的演示有效,但如果表结构不同,可能需要调整。
    • 样本表被简化了,我只列出了我的问题的相关字段。我的实际数据包含个人标识符,因此我尽可能接近实际格式。整个周末,我确实使用它并成功了!我添加了一个临时表,因为我的一些字段的名称需要更新(删除一些标点符号)。谢谢!
    猜你喜欢
    • 2023-02-18
    • 2014-09-07
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    相关资源
    最近更新 更多