SQL在过去12个月中选择多个计数,包括缺少的月份

时间:2014-08-08 14:00:04

标签: sql date count

我一直在尝试创建一个返回类似结果的SQL查询:

May     2013    P1  0
May     2013    P2  5
May     2013    P3  2
May     2013    P4  1
June    2013    P1  3
June    2013    P2  2
June    2013    P3  4
June    2013    P4  9
July    2013    P1  0
July    2013    P2  0
July    2013    P3  5
July    2013    P4  2

我的想法是我有两张桌子优先和工作:

Priority:
Name|Value
P1    9
P2    7
P3    5
P4    2
...

工作:

ID | PriorityValue | CompleteTime
1    9               03/04/2013
2    5               02/09/2013
3    7               12/01/2014
4    9               11/02/2014

如何为过去12个月或更长时间内的每项优先工作生成计数?

到目前为止,我已经查看了此Include monthly counts including months where data doesn't exist

的解决方案

我到目前为止的查询是:

;WITH d(d) AS 
(
  SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, '20130501'), 0))
  FROM ( SELECT TOP (DATEDIFF(MONTH, '20130501', '20140401') + 1) 
    n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
    FROM sys.all_objects ORDER BY [object_id] ) AS n
)
SELECT 
  d.d,
  DATENAME(MONTH, d.d) as [Month], 
  YEAR(d.d) as [Year], 
  Priority.Name, COUNT(Work.ID) AS Count
FROM d LEFT OUTER JOIN Work
  ON CompleteTime >= d.d
  AND CompleteTime < DATEADD(MONTH, 1, d.d) RIGHT OUTER JOIN Priority on Work.PriorityValue = Priority.Value
GROUP BY d.d, Priority.Name
ORDER BY d.d;

但它只会生成一个优先级为&gt的月份列表; 0.例如:

May     2013    P3  5
May     2013    P4  55
July    2013    P3  8
July    2013    P4  48
August  2013    P3  2
August  2013    P4  8

2 个答案:

答案 0 :(得分:0)

问题是您按Priority.Name分组,对于不存在的项目为空。要修复你必须给它们一个名字(我在下面使用'P1')然后它将起作用:

SELECT 
  d.d,
  DATENAME(MONTH, d.d) as [Month], 
  YEAR(d.d) as [Year], 
  ISNULL(Priority.Name,'P1'), 
  COUNT(Work.ID) AS Count
FROM d 
LEFT OUTER JOIN Work ON CompleteTime >= d.d AND CompleteTime < DATEADD(MONTH, 1, d.d)
RIGHT OUTER JOIN Priority on Work.PriorityValue = Priority.Value
GROUP BY d.d, ISNULL(Priority.Name,'P1')
ORDER BY d.d;

答案 1 :(得分:0)

如果有人在寻找解决方案,我使用CROSS JOIN而不是RIGHT OUTER JOIN解决了它,如下所示:

SELECT 
  d.d,
  DATENAME(MONTH, d.d) as [Month], 
  YEAR(d.d) as [Year], 
  ISNULL(Priority.Name,'P1'), 
  COUNT(Work.ID) AS Count
FROM d 
LEFT OUTER JOIN Work ON CompleteTime >= d.d AND CompleteTime < DATEADD(MONTH, 1, d.d)
CROSS JOIN Priority on Work.PriorityValue = Priority.Value
GROUP BY d.d, ISNULL(Priority.Name,'P1')
ORDER BY d.d;