简体   繁体   中英

SQL query to count incidents by year by month

I have one table called Incidents . I want a SQL query that returns the count of incidents split out by year, by month. The start year is 2010, however, the end year will be variable.

Example Incidents table:

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

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.

Using classic 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+

Using CHOOSE added UNION to cte to ensure to get zeros for missing years:

;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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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