【问题标题】:Combine Queries where one is recursive组合查询,其中一个是递归的
【发布时间】:2021-04-07 06:06:33
【问题描述】:

我有一个递归查询,它为上个月的每个小时创建一行,如下所示;

 WITH a AS (
    SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) AS [DateTime]
    UNION ALL
    SELECT dateadd(hour, 1, [DateTime])
    FROM a
    WHERE dateadd(hour, 1, [DateTime]) < EOMONTH(GETDATE(), -1)
    )
 SELECT 
     a.*

 FROM a

 OPTION (maxrecursion 0);

这会产生这些结果;

 DateTime
 2020-11-01 00:00:00.000
 2020-11-01 01:00:00.000
 2020-11-01 02:00:00.000
 etc.....

接下来,我有一个查询,计算上个月每位客户每小时的呼叫次数,如下 4 周平均值;

SELECT
DATEADD(hour, DATEDIFF(hour, 0,
    DATEADD(minute, 30 - DATEPART(minute, Timestamp + '00:30:00.000'),
    Timestamp)), 0)  as RoundedToHour,
Campaign,
COUNT(*)/4 AS Average

FROM [Reporting].[dbo].[New_Five9_CallLog] WITH (NOLOCK)

WHERE DATEDIFF(mm, Timestamp, GETDATE()) = 1
AND Call_Type = 'Inbound'

GROUP BY Campaign,
    DATEADD(hour, DATEDIFF(hour, 0,
        DATEADD(minute, 30 - DATEPART(minute, Timestamp + '00:30:00.000'),
        Timestamp)), 0)

这会产生以下结果;

RoundedToHour             Campaign     Average
2020-11-01 02:00:00.000   Client1      0
2020-11-01 04:00:00.000   Client2      2
etc....

我遇到的麻烦是将这两者结合起来。我最初的想法是在我的第二个查询中使用递归查询的 CTE 作为基本的 where 子句,但是由于您必须对 CTE 使用 WITH,而且我必须对递归查询使用 WITH,这不会直接工作,因为你不能嵌套 WITH's。

我正在寻找的最终结果是一个查询,它为每个客户生成上个月每个小时的 4 周平均呼叫次数。如果有人对如何实现我的最终目标有更好的建议,我愿意改变我做这一切的方式。

【问题讨论】:

标签: sql sql-server tsql common-table-expression


【解决方案1】:

您不能在子查询中声明 CTE,但您可以同时声明多个 CTE。所以声明两者,然后LEFT JOIN他们。

WITH a AS (
    SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) AS [DateTime]
    UNION ALL
    SELECT dateadd(hour, 1, [DateTime])
    FROM a
    WHERE dateadd(hour, 1, [DateTime]) < EOMONTH(GETDATE(), -1)
), b AS (
    SELECT
        DATEADD(hour, DATEDIFF(hour, 0,
            DATEADD(minute, 30 - DATEPART(minute, Timestamp + '00:30:00.000'),
            Timestamp)), 0)  as RoundedToHour,
        Campaign,
        COUNT(*)/4 AS Average
    FROM [Reporting].[dbo].[New_Five9_CallLog] WITH (NOLOCK)
    WHERE DATEDIFF(mm, Timestamp, GETDATE()) = 1
    AND Call_Type = 'Inbound'
    GROUP BY Campaign,
        DATEADD(hour, DATEDIFF(hour, 0,
            DATEADD(minute, 30 - DATEPART(minute, Timestamp + '00:30:00.000'),
            Timestamp)), 0)
)
SELECT a.*, b.*
FROM a
LEFT JOIN b on b.RoundedToHour = a.DateTime
OPTION (maxrecursion 0);

【讨论】:

  • 这不仅完美无缺,而且我还能够添加一些其他数据点以使其更具包容性。非常感谢您的帮助!
  • 除此技术外,我建议您熟悉使用 cross applyouter apply - 它们本质上允许您使用初始查询中的值加入子查询(或表值函数) .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-13
  • 1970-01-01
  • 1970-01-01
  • 2015-09-06
  • 1970-01-01
  • 2019-11-02
相关资源
最近更新 更多