使用基于集合的方法获取给定日期范围之间的特定日期

时间:2015-12-11 12:13:27

标签: sql sql-server tsql

按顺序获取所有Sunday datesSaturday dates 在给定date ranges之间,我使用了iterative solution,如下所示,

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

我想知道如何使用set based approach实现这一目标。有没有办法得到上述结果 使用set based approach

我使用迭代解决方案获得的输出如下所示。

enter image description here

3 个答案:

答案 0 :(得分:2)

确实没有&#34;基于集合&#34;当你以空集开始时的方法。您可以使用递归CTE替换代码。您可以通过以下方式获取开始日期:

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);

请注意,这不会验证星期几的要求。从第一天算起几周。

答案 1 :(得分:2)

这应该使用计数表来解决它:

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)

编辑改进版本:

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)

结果:

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

答案 2 :(得分:1)

用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

选中此link以了解这两种方法。