TSQL - 查询两个日期字段之间的日期列表
Posted
技术标签:
【中文标题】TSQL - 查询两个日期字段之间的日期列表【英文标题】:TSQL - Query a list of dates between two date fields 【发布时间】:2021-12-08 18:05:02 【问题描述】:数据:
DECLARE @Dates TABLE
(
[MyDate] DATE
, [WkStart] DATE
, [WkEnd] DATE
) ;
INSERT INTO @Dates
SELECT '2021-10-03'
, '2021-09-27'
, '2021-10-03'
UNION
SELECT '2021-10-21'
, '2021-10-18'
, '2021-10-24'
UNION ALL
SELECT '2021-10-23'
, '2021-10-18'
, '2021-10-24'
UNION
SELECT '2021-10-27'
, '2021-10-25'
, '2021-10-31' ;
目标:
输出 2 个字段。第一个 = 日期字段,第二个 = 位字段。日期字段将包含每条记录的 [WkStart] 和 [WkEnd] 之间的所有日期。当 [MyDate] 等于第一个字段的值时,位字段将为真。桌子很大,所以性能很重要。当 2+ [MyDate] 值属于同一周范围时,该周的日期不应重复。
预期输出:
我的尝试:
; WITH recrCTE AS
(
SELECT CAST ( [WkStart] AS DATETIME ) AS [DateVal]
, [WkEnd]
, [MyDate]
FROM @Dates
UNION ALL
SELECT [DateVal] + 1
, [WkEnd]
, [MyDate]
FROM recrCTE
WHERE [DateVal] + 1 <= [WkEnd]
)
SELECT [DateVal]
, IIF ( [MyDate] = [DateVal], 1, 0 ) AS [isMyDate]
FROM recrCTE
ORDER BY [DateVal]
OPTION ( MAXRECURSION 0 ) ;
当前输出:
这个解决方案有两个明显的问题。 1st,记录在同一日期范围内(10 月 21 日和 10 月 23 日)内重复 2 个以上的日期。第二,这两个日期都以 2 个不同的位值重复,因此不能简单地使用 DISTINCT。我觉得可能成为问题的第三个问题是性能。也许有一种更有效的方法来实现这一点(也许使用函数)而不是使用递归 CTE。
【问题讨论】:
对于您的1st
和2nd
问题,一个快速的方法是执行GROUP BY DateVal
、MAX(isMyDate)
。为了提高性能,请使用计数表而不是递归 cte
一周内最多可以有 7 行,对吗?你说这个表很大,你是否需要对整个表每次运行查询,或者你是否会有比所有时间更小的日期范围的合理谓词>?
【参考方案1】:
一周只能有 7 天时不需要递归;只需将 7 个值硬编码为 1-7,这样您就可以使用这些值将集合从 WkStart
爆炸到 6 天后。然后您可以有条件地在DateVal
上聚合该输出。
;WITH alldays AS
(
SELECT DateVal = DATEADD(DAY, days.n-1, d.WkStart),
d.MyDate
FROM @Dates AS d
CROSS JOIN (VALUES(1),(2),(3),(4),(5),(6),(7)) AS days(n)
-- if the table is large and performance is a concern, then:
-- WHERE d.? -- some reasonable where clause belongs here?
)
SELECT DateVal,
IsMyDate = MAX(CASE MyDate WHEN DateVal THEN 1 ELSE 0 END)
FROM alldays
GROUP BY DateVal
ORDER BY DateVal;
示例db<>fiddle
【讨论】:
谢谢亚伦!通过“大表”,我的意思是这个查询将成为可以跨越多年的报告过程的一部分,因此@Dates 可以变得很大(仍然少于 1K 记录)。无论如何,这是一个很好的解决方案。谢谢!!在阅读了 squirrel 的建议(也谢谢你)之后,我开始使用计数表类型的查询(双 CTE),虽然执行计划显示相同的成本,但您的执行计划更清洁。简单地交叉连接到 1-7 个值是有意义的。再次感谢!希望在未来的某个 SQL 星期六再次见到您。干杯! @007 没问题詹姆斯邦德! 为什么不;你只做0到6,那你就不需要-1
@Charlieface 好吧,根据我的经验,大多数来这里寻求帮助的人都不是基于 0 的思想家。
@007 这个周末开车去的时候看到的,很不错。以上是关于TSQL - 查询两个日期字段之间的日期列表的主要内容,如果未能解决你的问题,请参考以下文章