在SQL中转置许多聚合

时间:2018-10-18 18:51:13

标签: sql sql-server tsql

我有两个表cases,主表和activities,它们显示了针对某些情况所做的工作。

CREATE TABLE cases
    ([caseno] int, [case_detail] varchar(8), [date_received] datetime)
;

INSERT INTO cases
    ([caseno], [case_detail], [date_received])
VALUES
    (1, 'DETAIL A', '2018-04-01 00:00:00'),
    (2, 'DETAIL B', '2018-05-01 00:00:00'),
    (3, 'DETAIL C', '2018-06-01 00:00:00')
;

CREATE TABLE activities
    ([caseno] int, [activity] int, [team] varchar(1))
;

INSERT INTO activities
    ([caseno], [activity], [team])
VALUES
    (1, 00, 'A'),
    (1, 10, 'A'),
    (1, 00, 'A'),
    (1, 00, 'B'),
    (1, 90, 'C'),
    (1, 00, 'C'),
    (1, 00, 'A'),
    (2, 10, 'A'),
    (2, 00, 'A'),
    (2, 00, 'B'),
    (3, 90, 'C'),
    (3, 00, 'C')
;

我对汇总activities的{​​{1}}数据,除以activity = '00'并附加到team数据感兴趣。

我已经通过以下方式实现了这一目标,但我怀疑这并不是最佳选择。案例表大约有100万行,活动表大约有2亿行。

cases

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=92632c9af821935790a7986e6f654b13

2 个答案:

答案 0 :(得分:4)

您可以使用条件聚合:

SELECT c.caseno, case_detail, date_received,
   COUNT(CASE WHEN team = 'A' THEN 1 END) AS a,
   COUNT(CASE WHEN team = 'B' THEN 1 END) AS b,
   COUNT(CASE WHEN team = 'C' THEN 1 END) AS c
FROM cases c
LEFT JOIN activities a
  ON c.caseno = a.caseno
 AND a.activity = '00'
GROUP BY c.caseno, case_detail, date_received;

db<>fiddle demo


编辑

不键入GROUP BY中的所有列:

WITH cte AS (
 SELECT c.caseno,
   COUNT(CASE WHEN team = 'A' THEN 1 END) AS a,
   COUNT(CASE WHEN team = 'B' THEN 1 END) AS b,
   COUNT(CASE WHEN team = 'C' THEN 1 END) AS c
 FROM cases c
 LEFT JOIN activities a
   ON c.caseno = a.caseno
  AND a.activity = '00'
 GROUP BY c.caseno   -- only PK
)
SELECT * FROM cte JOIN cases c ON cte.caseno = c.caseno;

答案 1 :(得分:1)

枢轴解决方案

select *
from 
  ( select cs.*,A.team 
    from cases cs 
    join activities a on cs.caseno=a.caseno and a.activity = 00 
  ) C
pivot 
  (count(team)
   for team in ([A],[B],[C])  
  ) pvt

给我们相同的结果

sample