在SQL Server 2008+上,我正在尝试创建一个查询,该查询将是一个视图的代码(因此,只允许一个语句......对吗?),它返回一个包含所有可能日期的列(实际{表格datetime
的列insdate
的最小值和最大值之间的{1}}但空白时间内容。
我试过了:
dt
但它失败了,因为Msg 319太常见了。有趣的是,每个人都有'条款在未合并时按预期工作。我错过了一些像#34的规则;递归cte必须是第一个"?我怎样才能达到我的初衷?
答案 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)