【问题标题】:SQL select multiple counts in the last 12 months including missing monthsSQL 选择过去 12 个月内的多个计数,包括缺失的月份
【发布时间】:2014-08-08 14:00:04
【问题描述】:

我一直在尝试创建一个返回如下结果的 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 和 Work:

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;

但它只生成优先级计数> 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

【问题讨论】:

  • 什么数据库? (甲骨文?postgres?)

标签: sql date count


【解决方案1】:

问题是您按 Priority.Name 分组,对于不存在的项目,该名称为 null。要解决这个问题,你必须给它们起一个名字(我在下面使用了“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;

【讨论】:

  • 嗨,霍根,感谢您的回复。我使用您的查询得到了相同的结果。以下是输出示例:
    NULL NULL NULL P1 0 NULL NULL NULL P2 0 2013-05-01 00:00:00.000 May 2013 P3 6 2013-05-01 00:00:00.000 May 2013 P4 71 2013- 06-01 00:00:00.000 2013 年 6 月 P3 15 2013-06-01 00:00:00.000 2013 年 6 月 P4 35 2013-07-01 00:00:00.000 2013 年 7 月 P3 11 2013-07-01 00:00:00.000 2013 年 7 月 P4 79 2013-08-01 00:00:00.000 2013 年 8 月 P3 2 2013-08-01 00:00:00.000 2013 年 8 月 P4 8 2013-10-01 00:00:00.000 2013 年 10 月 P3 2 2014-04- 01 00:00:00.000 2014 年 4 月 P3 2
  • 抱歉,我不确定如何在评论中格式化代码,但结果看起来与我的问题中的相同。
  • @hihi - 那结果怎么错了,你得到了 12 行......这不是你想要的吗?
  • @hihi 或者你想为每个月的每个优先级设置一行吗?
  • 抱歉回复晚了。是的,我希望每个月的每个优先级都排一排,如问题所示。无论如何,我已经使用 CROSS JOIN 而不是 RIGHT OUTER JOIN 解决了​​它。谢谢。
【解决方案2】:

如果有人在寻找解决方案,我使用 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;

【讨论】:

    猜你喜欢
    • 2015-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    • 2012-03-23
    • 2020-05-29
    相关资源
    最近更新 更多