递归查询错误

时间:2018-02-27 13:06:57

标签: sql-server tsql recursion sql-view

在SQL Server 2008+上,我正在尝试创建一个查询,该查询将是一个视图的代码(因此,只允许一个语句......对吗?),它返回一个包含所有可能日期的列(实际{表格datetime的列insdate的最小值和最大值之间的{1}}但空白时间内容。

我试过了:

dt

但它失败了,因为Msg 319太常见了。有趣的是,每个人都有'条款在未合并时按预期工作。我错过了一些像#34的规则;递归cte必须是第一个"?我怎样才能达到我的初衷?

2 个答案:

答案 0 :(得分:2)

如果你想使用多个CTE,你不需要多次指定WITH,只需用逗号链接它们:

WITH CTE1 AS (...),
CTE2 AS (...),
CTE3 AS ....

但我完全推荐一种不同的方法。如果你有一个日历表,那么这将成为一个非常基本的查询:

WITH DateRange (MinDate, MaxDate) AS
(
    SELECT MIN(InsDate), MAX(InsDate) 
    FROM dt
)
SELECT  c.Date 
FROM    dbo.Calendar AS c
        INNER JOIN DateRange AS dr
            ON dr.MinDate <= c.Date
            AND dr.MaxDate >= c.Date;

如果您没有日历表,则可以动态生成日期列表。关于这一点的更多内容在这里:

第3部分特别相关,因为它涉及日期。

最简单的方法是生成一个与您的范围大小相关的连续数字列表,并将每个数字添加到您的开始日期,例如

WITH DateRange (MinDate, MaxDate) AS
(
    SELECT MIN(InsDate), MAX(InsDate)
    --FROM dt
    FROM (VALUES (CONVERT(DATE, '20170101')), (CONVERT(DATE, '20180101'))) dt (InsDate)
), Numbers AS
(   SELECT  Number = ROW_NUMBER() OVER(ORDER BY n1.n) - 1
    FROM    (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS n1 (n) 
    CROSS JOIN (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS n2 (n)
    CROSS JOIN (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS n3 (n)
)
SELECT  DATEADD(DAY, n.Number, dr.MinDate)
FROM    DateRange AS dr
        INNER JOIN Numbers AS n
            ON n.Number <= DATEDIFF(DAY, dr.MinDate, dr.MaxDate);

答案 1 :(得分:1)

将其更改为:

    ;with daterange(mindate,maxdate) as 
    (
        select min(insdate) as mindate,max(insdate) as maxdate from dt
    )
    , t(specific_day) AS (
      SELECT mindate FROM daterange    -- Seed Row
      UNION ALL
      SELECT specific_day+1 -- Recursion
      FROM t
      where specific_day+1<=(select maxdate from daterange)
    )
    select * from t
    option (maxrecursion 5000)