2016-06-15 13 views
1

두 날짜 사이에 모든 날짜를 가져 오려고합니다. arrival dateleaving date.두 날짜 사이의 모든 날짜를 가져 오는 재귀 쿼리를 작성하는 방법

재귀 쿼리를 시도했지만 작동하지 않았습니다.

;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

내가 그 시도 곳은 있지만, 아무튼 일하지 마라. dbo.Guest 에서 reserveddate 모든 SELECT GuestID, DATEADD (일, 1, dbo.Guest. ArrivalDate) DATEADD dbo.Guest 노동 조합 reserveddate 로 ( SELECT GuestID, ArrivalDate 같은 날짜 (하루, 1, dbo.Guest. ArrivalDate)

+0

쿼리의 재귀 부분에서'dbo.Guest '에'dates'을 (를) 추가해야합니다. – gofr1

+0

어떻게 할 수 있습니까 –

답변

1

당신은 재귀 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) 

출력 :

: 샘플을 바탕으로

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

EDIT1

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) 

출력 : 것은 이러한 유형의

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

죄송합니다, 제거했습니다. –

1

내 취향은 집계 테이블을 사용하는 것입니다. 이렇게 보이는 모든 시스템에 대한 견해를 유지합니다.

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 

이 방법으로는 항상 내 손끝에 집계 테이블이 있습니다. 탤리 테이블과 루프를 대체하는 방법에 대한 자세한 내용은 여기에서 읽을 수 있습니다. http://www.sqlservercentral.com/articles/T-SQL/62867/

현재 문제를 해결하기 위해 매우 간단합니다. 먼저 테이블과 샘플 데이터가 필요합니다.

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' 

여기에 집계 테이블의 기능이 실제로 표시됩니다. 귀하의 도전 과제에 대한 결과를 산출하는 것은이 코드만큼이나 간단합니다.

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 

재귀 CTE를 통해 접근이 유형의 또 다른 큰 장점

은 삼각형으로 알려진 사용에 가입하고 일부 성능 문제를 일으킬 수있다는 것이다. 삼각형 조인에 대한 자세한 정보가 있습니다. http://www.sqlservercentral.com/articles/T-SQL/61539/

0

, 연도 등을 선택 DATEADD에서, MONTH이

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) 

당신이 일주일 DAY를 변경하여 변경 사항을 날짜 간격을 변경할 수 있습니다 시도하고 DATEDIFF