2015-12-11 19 views
5

In-aby uzyskać wszystkie Sunday dates i Saturday dates pomiędzy danym date ranges Użyłem iterative solution jak poniżej,Get konkretnych dat między podaną datą zakresów stosując zestaw podejścia opartego

create TABLE #Dayweeks (id int IDENTITY(1,1),StartWeek DATETIME, EndWeek DATETIME) 

DECLARE @wkstartdate datetime = '2015-12-06', 
     @wkenddate datetime = '2016-04-05' 



WHILE (@wkstartdate <= @wkenddate) 
    BEGIN 
     INSERT INTO #Dayweeks 
     (
     StartWeek, EndWeek 
     ) 
     SELECT 
     @wkstartdate, DATEADD(wk,DATEDIFF(wk,0,@wkstartdate),6)-1 

     SELECT @wkstartdate = DATEADD(dd,7,@wkstartdate) 
    END 

Zastanawiam się, jak to osiągnąć przy użyciu set based approach. Czy istnieje sposób, aby uzyskać powyższy wynik za pomocą set based approach?

Dane wyjściowe, które otrzymałem za pomocą iteracyjnego rozwiązania, podano poniżej.

enter image description here

Odpowiedz

1

Sprawdź to z CTE:

Declare @DateFrom DateTime ='2011-07-01', 
      @DateTo DateTime = '2011-07-31' 
;WITH CTE(dt) 
AS 
(
     Select @DateFrom 
     Union All 
     Select DATEADD(d,1,dt)FROM CTE 
     Where dt<@DateTo 
) 
Select 
    DATENAME(dw,dt) day, dt 
from CTE 
where DATENAME(dw,dt)In('Sunday' , 'Saturday') 

--To understand more, comment above select and run this. 
select * from 
(
    select 'Sunday' day,dt from CTE 
    where DATENAME(dw,dt)In('Sunday') 
    union 
    select 'Saturday',dt from CTE 
    where DATENAME(dw,dt)In('Saturday') 

) a order by dt 

Sprawdź to link zrozumieć zarówno podejście.

+0

zwraca sobotę i niedzielę jako wiersze w jednej kolumnie . Potrzebuję soboty i niedzieli jako różnych kolumn. dzięki – bmsqldev

2

Naprawdę nie ma podejście „ustawić na bazie”, gdy zaczynasz z pustym zestawem. Możesz zastąpić swój kod rekurencyjnym CTE. Możesz uzyskać daty rozpoczęcia, wykonując:

with weeks as (
     select @wkstartdate as dte 
     union all 
     select dateadd(weeks, 1, dte) 
     from dte 
     where dte < @wkenddate 
) 
insert into #Dayweeks(Startweek, EndWeek) 
    select dte, dateadd(day, 6, dte) 
    from weeks 
option (maxrecursion 0); 

Pamiętaj, że to nie weryfikuje wymagań dnia tygodnia. Zalicza tylko tygodnie od pierwszego dnia.

2

To powinno go rozwiązać przy użyciu tabeli tally:

DECLARE @wkstartdate datetime = '2015-12-06', 
     @wkenddate datetime = '2016-04-05' 

;WITH N(N)AS 
(SELECT 1 FROM(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))M(N)), 
tally(N)AS(SELECT ROW_NUMBER()OVER(ORDER BY N.N)FROM N,N a,N b,N c,N d,N e,N f) 
, alldays as 
(
    SELECT 
    top (datediff(d, @wkstartdate, @wkenddate)) 
     cast(dateadd(d, N-1, @wkstartdate) as date) day 
    FROM tally 
) 
SELECT day 
FROM alldays 
WHERE datediff(d, 0, day) % 7 in(5,6) 

EDIT ulepszona wersja:

DECLARE @wkstartdate datetime = '2015-12-06', 
     @wkenddate datetime = '2016-04-05' 

;WITH N(N)AS 
(SELECT 1 FROM(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))M(N)), 
tally(N)AS(SELECT ROW_NUMBER()OVER(ORDER BY N.N)FROM N,N a,N b,N c,N d,N e,N f) 
SELECT 
    CAST(DATEADD(d, 0, N) as DATE) WEEKEND 
FROM tally 
WHERE 
    N between datediff(d, 0, @wkstartdate) and datediff(d, 0, @wkenddate) 
    AND N % 7 in(5,6) 

Wynik:

day 
2015-12-06 
2015-12-12 
2015-12-13 
... 
... 
2016-04-03