Stosując te dane próbki:
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
Spróbuj:
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;
Pierwsza sekcja zapytania jest rekurencyjne SELECT, który jest zamocowany przez wszystkie rzędy które przydział = 0, i którego poprzedni dzień albo nie istnieje albo ma przydział! = 0. To skutecznie zwraca ID: 1 i 3, które są datami początkowymi okresów, które chcesz powrócić.
Część rekurencyjna tego samego zapytania rozpoczyna się od wierszy zakotwiczenia i znajduje wszystkie kolejne daty, które również mają przypisanie = 0.Identyfikator SeedID śledzi zakotwiczone ID we wszystkich iteracjach.
Rezultatem tej pory to:
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
Następny kwerendy sub wykorzystuje prosty GROUP BY odfiltrować wszystkie daty rozpoczęcia dla każdego SeedID, a także zlicza dni.
Ostatnie pod-zapytanie robi to samo z datami końcowymi, ale tym razem liczba dni nie jest potrzebna, ponieważ już to mamy.
Ostateczne zapytanie SELECT łączy te dwa elementy, aby połączyć daty rozpoczęcia i zakończenia i zwraca je wraz z liczbą dni.
@ istari to data zakończenia kolumny w strukturze tabeli – Devjosh
Czy próbowałeś używać kursora? lub nie potrzebujesz kursorów – Vikram
Masz na myśli "kolejne", jak w "jeden dzień od siebie", lub jak w "sąsiednich, gdy wiersze są sortowane według daty"? tj. czy każda niepowtarzalna data pojawia się dokładnie raz w kolumnie "data"? – gcbenison