【问题标题】:List of specific day/days in a given date range给定日期范围内的特定日期/日期列表
【发布时间】:2015-10-08 20:33:01
【问题描述】:

我正在寻找给定日期范围内特定日期/日期的列表,我找到了这个

declare @d datetime
select @d = '20100101'  --'20090101'  if you want 2009 etc etc

select dateadd(dd,number,@d) from master..spt_values
where type = 'p'
and year(dateadd(dd,number,@d))=year(@d)
and DATEPART(dw,dateadd(dd,number,@d)) = 7

get date of all saturdays in a given year - sql server

我想知道我是否可以使用开始日期和结束日期来代替年份,并且可以获得像周六和周日这样的两天列表。

问候

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    递归选择from_dateTo_Date的所有日期,然后使用DATEPART检查是否是周末。

    declare @from_date as date---your from date
    declare @to_date as date---your to date
    
    ;WITH dates AS (
        SELECT CONVERT( DATE, @from_date) AS a
        UNION ALL
        SELECT DATEADD( DAY, 1, a )
        FROM   dates
        WHERE  DATEADD( DAY, 1, a ) <= @to_date --including the @to_date
    )
    SELECT a
    FROM   dates
    WHERE  DATEPART( dw, a ) IN ( 1, 7 ) --- Saturday Or Sunday
    

    如果你想检查 Only Sunday

    SELECT a
        FROM   dates
        WHERE  DATEPART( dw, a )=1
    

    如果你想只检查星期六

    SELECT a
        FROM   dates
        WHERE  DATEPART( dw, a )=7
    

    【讨论】:

      【解决方案2】:

      这为您提供@start 和@end 之间每一天的天数:

      declare @start date = '20151001', @end date = '20151017'
      Select c = DATEDIFF(DAY, @start, @end)/ 7
           + case when (7 + DATEPART(WEEKDAY, @start) + (DATEDIFF(DAY, @start, @end)% 7) - d) % 7 <= (DATEDIFF(DAY, @start, @end)%7) then 1 else 0 end
      From (values(1), (2), (3), (4), (5), (6), (7)) as days(d)
      

      输出:

      Day 1   2
      Day 2   2
      Day 3   2
      Day 4   2
      Day 5   3
      Day 6   3
      Day 7   3
      

      它完全避免在@start 和@end 之间的每一天使用递归CTE 和DATEADD。这只是一些数学运算。

      对于多个日期,您也可以使用类似的方法,尽管它在大范围内效率不高:

      declare @start date = '20151001', @end date = '20151017'
      
      Select DATEADD(DAY, n, @start), DATEPART(WEEKDAY, DATEADD(DAY, n, @start))
      From (
          Select top(DATEDIFF(DAY, @start, @end)+1) ROW_NUMBER() over(order by n)-1
          From (
              Select 1 From (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as v1(n)
              Cross Join (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as v2(n)
              Cross Join (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as v3(n)
          ) as v(n)
      ) as o(n)
      Where DATEPART(WEEKDAY, DATEADD(DAY, n, @start)) in (7, 1)
      

      输出:

      DATE        WEEKDAY
      2015-10-03  7
      2015-10-04  1
      2015-10-10  7
      2015-10-11  1
      2015-10-17  7
      

      这里,7 = 星期六,1 = 星期日。您可以添加 1 到 7 之间的任何值,或者它可以来自另一个表。 如果您使用 DATENAME,则可以将其替换为日期名称。

      然后,您只需添加一个分组依据和/或一个总和即可获得周六和周日的数量。

      V1/V2/V3 避免使用递归查询并快速生成从 0 到 X(最多 999)的数字列表。 X 是 @start 和 @end 之间的天数之差。如果您需要 10.000 天范围(等等...),请添加 v4,但 1000 天足够使用 2 年以上,差不多 3 年。

      【讨论】:

        【解决方案3】:

        对 rajeshmpanchal 脚本的小修改。

        1. 为 cte maxrecursion 添加 - 默认为 100 行。
        2. set datefirst 1 /* 星期一 *

        你可以试试这个:

        set datefirst 1 /* monday */
        
        declare @v_date_start datetime
        declare @v_date_stop datetime
        
        set @v_date_start = '2015-05-01'
        set @v_date_stop = '2020-10-01' 
        
        ;with date_cte 
        as
        (
            select  @v_date_start [date]
            union all
            select  dateadd(day, 1, cte.date) [date]        
            from    date_cte [cte]
            where   dateadd(day, 1, cte.date) <= @v_date_stop 
        
        )
        
        select  cte.date
            ,   datename(dw, cte.date) [day_name]
        from    date_cte [cte]
        where   datepart(dw, cte.date) in (6,7)
        option  (maxrecursion 0)
        

        【讨论】:

        • 谢谢大家。问题解决了。问候和尊重。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-14
        • 1970-01-01
        • 1970-01-01
        • 2017-02-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多