2016-08-29 65 views
0
create table #temp (date date) 
declare @X date 
set @X = '2016-7-01' 
declare @Y date 
set @Y = cast (getdate() as date) 
while(@X<[email protected]) 
begin 
if (datename(WEEKDAY,@X) = 'Sunday') 
insert into #temp values (@X) 
set @X = cast(((cast(@X as datetime))+1)as date) 
continue 
end 
select * from #temp 
drop table #temp 

是否有可能使用CTE遞歸編寫上述查詢?是否可以使用CTE遞歸編寫以下查詢?

回答

1

您可以使用CTE創建數字表。然後,您可以使用數字表,讓您的日期,就像這樣:

Declare @Startdate Datetime = '2016-07-01' 
Declare @EndDate Datetime = '2016-08-29' 

;with 
N0 as (SELECT 1 as n UNION ALL SELECT 1) 
,N1 as (SELECT 1 as n FROM N0 t1, N0 t2) 
,N2 as (SELECT 1 as n FROM N1 t1, N1 t2) 
,N3 as (SELECT 1 as n FROM N2 t1, N2 t2) 
,N4 as (SELECT 1 as n FROM N3 t1, N3 t2) 
,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N4) 
SELECT DATEADD(day,num-1,@startdate) as thedate 
FROM nums 
WHERE num <= DATEDIFF(day,@startdate,@enddate) + 1 
and datename(WEEKDAY, DATEADD(day,num-1,@startdate)) = 'Sunday' 

每個表(N0nums)有效地提升了在前面的「表」的行數,所以你最終65,536行號在nums(根據需要添加或刪除表NX可以做更少或更多)。然後,使用數字表將日期添加到您的開始日期(SELECT DATEADD(day,num-1,@startdate) as thedate),其中返回的日期在您的日期範圍內,並且weekday是星期日。

而且,因爲1 nums開頭的數字,我們用nums-1在我們的選擇,從而避免跳過本系列上的第一次約會,有效地給我們DATEADD(day, 0, @startdate)我們的第一排。

0

你可以嘗試像這裏解釋:http://blog.sqlauthority.com/2009/12/29/sql-server-get-date-of-all-weekdays-or-weekends-of-the-year/

DECLARE @StartDate DATETIME 
DECALRE @EndDate DATETIME 

SET @StartDate = '2016-07-01' 
SET @EndDate = GETDATE() 

;WITH cte AS (

    SELECT 
     1 AS DayID, 
     @StartDate AS FromDate, 
     DATENAME(dw, @StartDate) AS Dayname 

    UNION ALL 

    SELECT 
     cte.DayID + 1 AS DayID, 
     DATEADD(d, 1, cte.FromDate), 
     DATENAME(dw, DATEADD(d, 1, cte.FromDate)) AS Dayname 
    FROM cte 
    WHERE DATEADD(d, 1, cte.FromDate) < @EndDate 
) 
SELECT FromDate AS Date, Dayname 
FROM cte 
WHERE Dayname IN ('Sunday') 

我想還有的是用數字表和7倍這樣做更有效的方式(這取決於有多少約會,你需要得到,可能會從你的開始日期預先計算出第一個星期日,然後加入數字表中所有7的因子),但上面的工作也足夠好。

0
;with cte 
as 
(
select getdate() as datee 
union all 
select dateadd(day,1,datee) 
from cte 
where datediff(day,getdate(),datee)<100 
) 
select * from cte 
where datename(WEEKDAY,datee) = 'Sunday' 

您將達到最大遞歸限制爲好,avoid..that使用類似下面..

option (MaxRecursion 0) 

我會解決這個用數字表,如果我不被需要約束使用遞歸CTE,這也比遞歸CTE的方式更快..

select 
dateadd(day,n,getdate()) as datee 
from numbers 
where n<100 and datename(weekday,dateadd(day,n,getdate()))='sunday' 

要了解爲什麼你需要的數字表,檢查此鏈接.. https://dba.stackexchange.com/questions/11506/why-are-numbers-tables-invaluable