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;
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];
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.