简体   繁体   English

SQL查询逐个计算事件

[英]SQL query to count incidents by year by month

I have one table called Incidents . 我有一个叫做Incidents表。 I want a SQL query that returns the count of incidents split out by year, by month. 我想要一个SQL查询,它返回按月拆分的事件数。 The start year is 2010, however, the end year will be variable. 开始年份是2010年,但是,结束年份将是变数。

Example Incidents table: 示例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

Query Returns: 查询返回:

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

How can I do that query? 我该怎么做那个查询? Where do I start? 我从哪里开始?

One option is to use conditional aggregation: 一种选择是使用条件聚合:

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)

With pivoting: 通过旋转:

;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

Another way to do without a pivot you could use a join: 没有枢轴的另一种方法是使用连接:

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

If you want year to be "dynamic" you have the CTE like this 如果你想让一年变得“充满活力”,你就会有这样的CTE

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

but this has the same drawback as the sgeddes solution -- years with no values don't show up. 但这与sgeddes解决方案具有相同的缺点 - 没有值的年份没有显示出来。

Using classic PIVOT : 使用经典PIVOT

Data: 数据:

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);

Query: 查询:

;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+ SQL Server 2012+

Using CHOOSE added UNION to cte to ensure to get zeros for missing years: 使用CHOOSE添加UNION以确保在缺失年份时获得零:

;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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM