資料:
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 ) ;
電流輸出:

這個解決方案有兩個明顯的問題。第一,記錄在同一日期范圍內的 2 個以上日期重復(10 月 21 日和 10 月 23 日)。第二,這兩個日期都用 2 個不同的位值重復,因此不能簡單地使用 DISTINCT。我覺得可能成為問題的第三個是性能。也許有一種更有效的方法來實作這一點(也許使用函式)而不是使用遞回 CTE。
uj5u.com熱心網友回復:
當一周只能有 7 天時,您不需要遞回;只需對 1-7 的 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;
- 示例資料庫<>小提琴
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/331444.html
標籤:sql sql-server 日期 查询语句 sql-server-2016
上一篇:在R中對連續日期進行分組
