SQL - 查询两个日期字段之间的日期列表

TSQL - Query a list of dates between two date fields

数据:

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] 等于第一个字段的值时,位字段将为真。 table 非常大,因此性能很重要。当 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 ) ;

当前输出:

此解决方案有两个明显的问题。第一,记录重复属于同一日期范围内的 2 个以上日期(10 月 21 日和 10 月 23 日)。第二,这两个日期都以 2 个不同的位值重复,因此不能简单地使用 DISTINCT。第三个我觉得可能成为问题的是性能。也许有更有效的方法来实现这一点(也许使用函数)而不是使用递归 CTE。

当一周只有 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;