2016-06-15 14 views
1

Ich möchte alle Daten zwischen zwei Daten arrival date und leaving date erhalten.Wie man rekursive Abfrage erstellt, um alle Daten zwischen zwei Daten zu erhalten

Ich habe diese rekursive Abfrage versucht, aber es hat nicht funktioniert.

;with dates as ( 
SELECT GuestID, ArrivalDate as reserveddate 
from dbo.Guest 
union all 
SELECT GuestID, dateadd (day,1,dbo.Guest. ArrivalDate) as reserveddate 
from dbo.Guest 
where dateadd (day,1,dbo.Guest. ArrivalDate) <dbo.Guest.leavingate 
) 

SELECT * 
from dates 
option (maxrecursion 0) 
+0

ich versucht, aber es doesn arbeite nicht. mit Daten als ( SELECT GuestID, Ankunftstag als reserveddate von dbo.Guest Vereinigung all SELECT GuestID, dateadd (Tag, 1, dbo.Guest. Ankunftstag) als reserveddate von dbo.Guest wo dateadd (Tag, 1, dbo.Guest. ArrivalDate)

+0

Sie müssen 'dates' zu' dbo.Guest 'im rekursiven Teil der Abfrage beitreten. – gofr1

+0

wie kann ich das tun –

Antwort

1

Sie müssen rekursive CTE:

DECLARE @arrival_date date = '2016-01-01', 
     @leaving_date date = '2016-02-01' 

;WITH cte AS (
SELECT @arrival_date as date_ 
UNION ALL 
SELECT CAST(DATEADD(day,1,date_) as date) 
FROM cte 
WHERE date_ < @leaving_date 
) 

SELECT * 
FROM cte 
OPTION (MAXRECURSION 0) 

Ausgang:

date_ 
2016-01-01 
2016-01-02 
2016-01-03 
... 
2016-01-30 
2016-01-31 
2016-02-01 

EDIT1

Basierend auf Ihrer Probe:

EDIT2

;WITH Guests AS (
SELECT 1 as GuestID, 
     '2016-01-01' ArrivalDate, 
     '2016-01-05' LeavingDate 
UNION ALL 
SELECT 2 , 
     '2016-06-17', 
     '2016-06-20' 
), cte AS (
SELECT GuestID, CAST(ArrivalDate as date) as date_ 
FROM Guests 
UNION ALL 
SELECT c.GuestID, CAST(DATEADD(day,1,date_) as date) 
FROM cte c 
INNER JOIN Guests g 
    ON g.GuestID = c.GuestID 
WHERE date_ < g.LeavingDate 
) 

SELECT * 
FROM cte 
ORDER BY GuestID, date_ 
OPTION (MAXRECURSION 0) 

Ausgang:

GuestID date_ 
1 2016-01-01 
1 2016-01-02 
1 2016-01-03 
1 2016-01-04 
1 2016-01-05 
2 2016-06-17 
2 2016-06-18 
2 2016-06-19 
2 2016-06-20 
+0

Entschuldigung, ich habe es entfernt –

1

Meine Vorliebe für diese Art der Sache ist, eine tally Tabelle zu verwenden. Ich behalte jedes System im Auge, das so aussieht.

create View [dbo].[cteTally] as 

WITH 
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 
select N from cteTally 
GO 

Auf diese Weise habe ich jederzeit einen Tally-Tisch an meinen Fingerspitzen. Sie können mehr über Tally-Tabellen lesen und wie sie hier Loops ersetzen. http://www.sqlservercentral.com/articles/T-SQL/62867/

Um Ihr aktuelles Problem zu lösen, wird dies ziemlich einfach. Zuerst brauchen wir eine Tabelle und einige Beispieldaten.

create table #Guest 
(
    GuestID int identity 
    , ArrivalDate date 
    , DepartureDate date 
) 

insert #Guest 
select '2016-06-01', '2016-06-15' union all 
select '2016-07-01', '2016-07-12' 

Hier ist, wo die Macht der Tally-Tabelle wirklich zeigt. Die Ausgabe für Ihre Herausforderung ist so einfach wie dieser Code.

SELECT GuestID 
    , ArrivalDate 
    , DepartureDate 
    , DATEADD(Day, N - 1, ArrivalDate) as EachDate 
from #Guest g 
join cteTally t on t.N <= DATEDIFF(day, ArrivalDate, DepartureDate) + 1 
order by GuestID 
    , EachDate 

Der andere große Vorteil dieser Art von Ansatz über eine rekursiven CTE ist, dass Sie verwenden, was als Dreieck bekannt ist, verbinden und können einige Performance-Probleme verursachen. Hier finden Sie weitere Informationen zu Dreiecksverbindungen. http://www.sqlservercentral.com/articles/T-SQL/61539/

0

Try This

DECLARE @DateFrom DateTime = DATEADD(DAY,DATEDIFF(DAY,0,GETDATE())-5,0) 
    DECLARE @DateTo DateTime = CONVERT(DATE,GETDATE()) 

    ;WITH Numbers (Number) AS (
     SELECT row_number() OVER (ORDER BY object_id) 
     FROM sys.all_objects 
    ) 

    SELECT dateadd(DAY, number-1, @DateFrom)   
    FROM Numbers 
    WHERE number <= datediff(DAY, @DateFrom-1, @DateTo-1) 

Sie die Änderung durch eine Änderung DAY nach Woche, Monat, Jahr usw. in der Auswahl dateadd das Datum Intervall ändern können und das, wo datediff