不确定如何在使用GROUP BY时执行多个嵌套的SELECT语句

时间:2016-02-02 21:36:03

标签: sql sql-server

下午好,

目前我的功能代码可用于确定一段时间内已打开的工单数和已关闭的工单数。我现在想要添加在那段时间之前打开的工单数量;我有代码产生我想要的结果,但我很难搞清楚如何将我的select语句内置到初始代码中,所以我不必分配静态日期。它会更容易向您展示我目前拥有的和我期望得到的东西。

SELECT o.dateinfo
    ,opened
    ,closed
FROM (
    SELECT MONTH(org_date) + (YEAR(org_date) * 100) AS dateinfo
        ,COUNT(wo) AS opened
    FROM wkaw
    WHERE org_date >= DATEFROMPARTS(YEAR(GETDATE()) - 1, MONTH(GETDATE()), 01)
    GROUP BY MONTH(org_date) + (YEAR(org_date) * 100)
    ) o
INNER JOIN (
    SELECT MONTH(cmpl_date) + (YEAR(cmpl_date) * 100) AS dateinfo
        ,COUNT(wo) AS closed
    FROM wkaw
    WHERE cmpl_date >= DATEFROMPARTS(YEAR(GETDATE()) - 1, MONTH(GETDATE()), 01)
        AND cmpl_date IS NOT NULL
    GROUP BY MONTH(cmpl_date) + (YEAR(cmpl_date) * 100)
    ) c ON o.dateinfo = c.dateinfo
ORDER BY o.dateinfo

目前产生这些结果

dateinfo  |  opened  |  closed
--------------------------------
201502    |   285    |    587
201503    |   519    |    345
201504    |   494    |    398
201505    |   415    |    430
201506    |   578    |    465
201507    |   409    |    646
201508    |   501    |    417
201509    |   430    |    347
201510    |   491    |    983
201511    |   657    |    455
201512    |   468    |    366
201601    |   723    |   1105
201602    |    54    |     60

然后我得到以下select语句,这些语句获取了我想要的每个条款的信息,但它们使用静态日期而不是像我上面那样自动生成。

SELECT COUNT(wo) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,02,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,02,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,03,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,03,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,04,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,04,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,05,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,05,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,06,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,06,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,07,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,07,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,08,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,08,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,09,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,09,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,10,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,10,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,11,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,11,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2015,12,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2015,12,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2016,01,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2016,01,01)
SELECT COUNT(*) FROM wkaw WHERE (cmpl_date >= DATEFROMPARTS(2016,02,01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(2016,02,01)

这些结果如下

1  |  2187
1  |  1885
1  |  2059
1  |  2155
1  |  2140
1  |  2253
1  |  2016
1  |  2100
1  |  2183
1  |  1691
1  |  1893
1  |  1995
1  |  1613

这些数字确实显示了我的期望。我想看到的结果是

dateinfo  |   open_wo_count  |  opened  |  closed
---------------------------------------------------
201502    |      2187        |   285    |    587
201503    |      1885        |   519    |    345
201504    |      2059        |   494    |    398
201505    |      2155        |   415    |    430
201506    |      2140        |   578    |    465
201507    |      2253        |   409    |    646
201508    |      2016        |   501    |    417
201509    |      2100        |   430    |    347
201510    |      2183        |   491    |    983
201511    |      1691        |   657    |    455
201512    |      1893        |   468    |    366
201601    |      1995        |   723    |   1105
201602    |      1613        |    54    |     60

我尝试了一些不同的方法,但它们都产生了不可预期的结果,我确信这只是因为我不知道如何。任何帮助将不胜感激。

干杯, 乔纳森

3 个答案:

答案 0 :(得分:0)

您可以创建一个存储所需的所有月初日期的表。 (这可以是您生成一次的实用程序表,也可以是即时生成的临时表。)

在你的情况下,我们可能会作弊。 只要每个月至少有一个工作单,我们就可以使用工单表本身来列出我们需要的日期。类似的东西:

SELECT DISTINCT(DATEFROMPARTS(YEAR(org_date),MONTH(org_date),01)) AS d FROM wkaw

我相信这些是你想要的日期。现在我们从这个“表”中选择日期以及一个子查询,该子查询计算每个日期的开放工作量。类似的东西:

SELECT MONTHSTART.d,
(SELECT COUNT(wo) FROM wkaw WHERE (cmpl_date >= MONTHSTART.d OR cmpl_date IS NULL) AND org_date < MONTHSTART.d)
FROM (SELECT DISTINCT(DATEFROMPARTS(YEAR(org_date),MONTH(org_date),01)) AS d FROM wkaw) MONTHSTART

这并没有给你最后的查询,但它非常接近。要将其与原始查询联系起来,请尝试将SELECT MONTHSTART.d替换为SELECT MONTH(MONTHSTART.d) + (YEAR(MONTHSTART.d)*100) as dateinfo,并将其与原始查询结合使用。

答案 1 :(得分:0)

尝试使用子选择。我还必须转换日期才能将它们与o.dateinfo进行比较。这样您就不必手动构建日期,因为它们已存在于dateinfo中。

SELECT o.dateinfo
    , (SELECT COUNT(*) FROM wkaw WHERE (CONVERT(CHAR(6), cmpl_date, 112) >= o.dateinfo OR cmpl_date IS NULL) AND CONVERT(CHAR(6), org_date, 112) < o.dateinfo) AS open_wo_count
    ,opened
    ,closed
FROM (
    SELECT MONTH(org_date) + (YEAR(org_date) * 100) AS dateinfo
        ,COUNT(wo) AS opened
    FROM wkaw
    WHERE org_date >= DATEFROMPARTS(YEAR(GETDATE()) - 1, MONTH(GETDATE()), 01)
    GROUP BY MONTH(org_date) + (YEAR(org_date) * 100)
    ) o
INNER JOIN (
    SELECT MONTH(cmpl_date) + (YEAR(cmpl_date) * 100) AS dateinfo
        ,COUNT(wo) AS closed
    FROM wkaw
    WHERE cmpl_date >= DATEFROMPARTS(YEAR(GETDATE()) - 1, MONTH(GETDATE()), 01)
        AND cmpl_date IS NOT NULL
    GROUP BY MONTH(cmpl_date) + (YEAR(cmpl_date) * 100)
    ) c ON o.dateinfo = c.dateinfo
ORDER BY o.dateinfo

答案 2 :(得分:0)

如果您进行交叉连接回Wkaw表,那么您将获得此表中每个条目的13个重复项。然后,您可以将cmpl_dateorg_date与之前在两个子查询中创建的dateinfo进行比较。

实施例

SELECT o.dateinfo
    ,SUM(Case when (cmpl_date >= DATEFROMPARTS(Left(o.dateinfo,4),Right(o.dateinfo,2),01) OR cmpl_date IS NULL) AND org_date < DATEFROMPARTS(Left(o.dateinfo,4),Right(o.dateinfo,2),01) THEN 1 ELSE 0 END) AS open_wo_count
    ,MAX(opened) as opened
    ,MAX(closed) as closed
FROM (
    SELECT MONTH(org_date) + (YEAR(org_date) * 100) AS dateinfo
        ,COUNT(wo) AS opened
    FROM wkaw
    WHERE org_date >= @DateStart
    GROUP BY MONTH(org_date) + (YEAR(org_date) * 100)
    ) o
INNER JOIN (
    SELECT MONTH(cmpl_date) + (YEAR(cmpl_date) * 100) AS dateinfo
        ,COUNT(wo) AS closed
    FROM wkaw
    WHERE cmpl_date >= @DateStart
        AND cmpl_date IS NOT NULL
    GROUP BY MONTH(cmpl_date) + (YEAR(cmpl_date) * 100)
    ) c ON o.dateinfo = c.dateinfo
CROSS JOIN Wkaw W
GROUP BY o.dateinfo
ORDER BY o.dateinfo

您必须取开启和关闭计数的最大值或最小值(但这些都是相同的,所以没有问题)