採用該試樣數據:
CREATE TABLE MyTable (ID INT, Date DATETIME, Allocation INT);
INSERT INTO MyTable VALUES (1, {d '2012-01-01'}, 0);
INSERT INTO MyTable VALUES (2, {d '2012-01-02'}, 2);
INSERT INTO MyTable VALUES (3, {d '2012-01-03'}, 0);
INSERT INTO MyTable VALUES (4, {d '2012-01-04'}, 0);
INSERT INTO MyTable VALUES (5, {d '2012-01-05'}, 0);
INSERT INTO MyTable VALUES (6, {d '2012-01-06'}, 5);
GO
嘗試這種情況:
WITH DateGroups (ID, Date, Allocation, SeedID) AS (
SELECT MyTable.ID, MyTable.Date, MyTable.Allocation, MyTable.ID
FROM MyTable
LEFT JOIN MyTable Prev ON Prev.Date = DATEADD(d, -1, MyTable.Date)
AND Prev.Allocation = 0
WHERE Prev.ID IS NULL
AND MyTable.Allocation = 0
UNION ALL
SELECT MyTable.ID, MyTable.Date, MyTable.Allocation, DateGroups.SeedID
FROM MyTable
JOIN DateGroups ON MyTable.Date = DATEADD(d, 1, DateGroups.Date)
WHERE MyTable.Allocation = 0
), StartDates (ID, StartDate, DayCount) AS (
SELECT SeedID, MIN(Date), COUNT(ID)
FROM DateGroups
GROUP BY SeedID
), EndDates (ID, EndDate) AS (
SELECT SeedID, MAX(Date)
FROM DateGroups
GROUP BY SeedID
)
SELECT StartDates.StartDate, EndDates.EndDate, StartDates.DayCount
FROM StartDates
JOIN EndDates ON StartDates.ID = EndDates.ID;
查詢的第一部分是一個遞歸SELECT,這是由是所有行錨定分配= 0,並且其前一天或者不存在或者分配!= 0.這實際上會返回ID:1和3,這是您想要返回的時間段的開始日期。
該查詢的遞歸部分從錨點行開始,並查找也具有分配= 0的所有後續日期。SeedID通過所有迭代跟蹤錨定的ID。
到目前爲止的結果是這樣的:
ID Date Allocation SeedID
----------- ----------------------- ----------- -----------
1 2012-01-01 00:00:00.000 0 1
3 2012-01-03 00:00:00.000 0 3
4 2012-01-04 00:00:00.000 0 3
5 2012-01-05 00:00:00.000 0 3
下一個子查詢使用簡單GROUP BY過濾掉所有的開始日期爲每個SeedID,並且還計算了天。
最後一個子查詢與結束日期完成相同的事情,但是這次不需要日計數,因爲我們已經有了這個。
最終的SELECT查詢將這兩者結合在一起組合起始日期和結束日期,並將它們與日計數一起返回。
@ istari是結束日期您的表結構中的一列 – Devjosh 2012-02-14 10:09:04
您嘗試過使用光標嗎?或者您不需要遊標 – Vikram 2012-02-14 10:31:31
您是指「間隔一天」中的「連續」,還是指「當行按日期排序時鄰近」?即每個唯一的日期是否在'日期'列中恰好出現一次? – gcbenison 2012-02-14 13:40:25