SQL查询逐个计算事件

时间:2015-10-27 19:04:13

标签: sql sql-server count

我有一个名为Incidents的表。我想要一个SQL查询,它返回按月拆分的事件数。开始年份是2010年,但结束年份将是变数。

示例Incidents表:

DateLogged    IncidentRef
-----------   ------------
2015-04-05    1
2014-06-04    2
2013-01-01    3
2012-12-10    4
2011-10-15    5
2010-10-01    6
2012-12-11    7
2011-10-10    8
2010-10-10    9

查询返回:

Year Jan Fev Mar Abr Mai Jun Jul Ago Set Out Nov Dez
2010  0   0   0   0   0   0   0   0   0   2   0   0
2011  0   0   0   0   0   0   0   0   0   2   0   0
2012  0   0   0   0   0   0   0   0   0   0   0   2
2013  1   0   0   0   0   0   0   0   0   0   0   0
2014  0   0   0   0   0   1   0   0   0   0   0   0
2015  0   0   0   1   0   0   0   0   0   0   0   0

我该如何进行查询?我从哪里开始?

4 个答案:

答案 0 :(得分:5)

一种选择是使用条件聚合:

select year(datelogged), 
   sum(case when month(datelogged) = 1 then 1 else 0 end) Jan,
   sum(case when month(datelogged) = 2 then 1 else 0 end) Feb,
   ...,
   sum(case when month(datelogged) = 12 then 1 else 0 end) Dec
from yourtable
group by year(datelogged)

答案 1 :(得分:3)

使用透视:

;with cte as(select year(date) y, month(date) m, ref from table)
select * from cte
pivot(count(ref) for m in([1],[2],...,[12]))p

答案 2 :(得分:1)

没有透视的另一种方法是使用连接:

with years as
(
   SELECT 2010 as y
     UNION ALL
   SELECT 2011
     UNION ALL
   SELECT 2012
     UNION ALL
   SELECT 2013
     UNION ALL
   SELECT 2014
     UNION ALL
   SELECT 2015
)
select years.y, 
  sum(case when month(DateLogged) = 1 then 1 else 0) as jan,
  sum(case when month(DateLogged) = 2 then 1 else 0) as feb,
  sum(case when month(DateLogged) = 3 then 1 else 0) as mar,
  sum(case when month(DateLogged) = 4 then 1 else 0) as apr,
  -- ...
  sum(case when month(DateLogged) = 12 then 1 else 0) as dec,

from years y
left join incidents i on y.y = year(i.DateLogged)
group by y.DateLogged

如果你想让一年变得“充满活力”,那你就有了这样的CTE

with years as
(
   SELECT DISTINCT year(i.DateLogged) FROM incidents 
)

但这与sgeddes解决方案具有相同的缺点 - 没有值的年份没有出现。

答案 3 :(得分:1)

使用经典 PIVOT

数据:

CREATE TABLE #Incidents(
   DateLogged  DATE  NOT NULL PRIMARY KEY
  ,IncidentRef INTEGER  NOT NULL );
INSERT INTO #Incidents(DateLogged,IncidentRef) VALUES 
    ('2015-04-05',1),('2014-06-04',2),('2013-01-01',3),
    ('2012-12-10',4),('2011-10-15',5),('2010-10-01',6),
    ('2012-12-11',7),('2011-10-10',8),('2010-10-10',9);

查询:

;WITH cte AS
(
  SELECT [year] = YEAR(DateLogged),
         [month] = CASE MONTH(DateLogged)
                      WHEN 1 THEN 'Jan'  WHEN 2 THEN 'Fev'
                      WHEN 3 THEN 'Mar'  WHEN 4 THEN 'Abr'
                      WHEN 5 THEN 'Mai'  WHEN 6 THEN 'Jun'
                      WHEN 7 THEN 'Jul'  WHEN 8 THEN 'Ago'
                      WHEN 9 THEN 'Set'  WHEN 10 THEN 'Out'
                      WHEN 11 THEN 'Nov' WHEN 12 THEN 'Dez'
                    END,
         IncidentRef
  FROM #Incidents  
)
SELECT [Year],Jan, Fev, Mar, Abr, Mai, Jun, Jul, Ago, [Set], Out, Nov, Dez
FROM cte
PIVOT (
  COUNT(IncidentRef)
  FOR [month]  IN (Jan, Fev, Mar, Abr, Mai, Jun,Jul, Ago, [Set], Out, Nov,Dez)
) AS piv;

LiveDemo

SQL Server 2012 +

使用CHOOSE添加UNION cte以确保错失年份的零:

;WITH cte AS
(
  SELECT [year] = YEAR(DateLogged),
         [month] = CHOOSE(MONTH(DateLogged),'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'),       
         IncidentRef
  FROM #Incidents
  UNION ALL
  SELECT [year], NULL, NULL
  FROM (VALUES (2010),(2011),(2012),(2013),(2014),(2015)) AS t([year])
)
SELECT [Year],Jan, Fev, Mar, Abr, Mai, Jun, Jul, Ago, [Set], Out, Nov, Dez
FROM cte
PIVOT (
  COUNT(IncidentRef)
  FOR [month]  IN (Jan, Fev, Mar, Abr, Mai, Jun,Jul, Ago, [Set], Out, Nov,Dez)
) AS piv
ORDER BY [Year];

LiveDemo2