【问题标题】:Find Mondays between 2 dates查找 2 个日期之间的星期一
【发布时间】:2015-06-11 10:01:21
【问题描述】:

我需要显示给定日期范围内所有星期一的日期。

例如,如果我的开始日期是01/05/2015,结束日期是31/05/2015,我需要显示

04/05/2015
11/05/2015
18/05/2015
25/05/2015

这怎么可能?

【问题讨论】:

  • 你有所有(可能的)日期的帮助表吗?
  • @jarlh 您可以使用递归 CTE(通用表表达式)创建这样的辅助表。
  • 这是日历表的完美用例,每个数据库都应该有一个。

标签: sql-server sql-server-2008 ssrs-2008


【解决方案1】:

参考:Select dates of a day between two dates.

SELECT [Day],[Dt] FROM dbo.fnGetDatesforAday('7/1/2008','8/31/2008','Sunday')


CREATE FUNCTION fnGetDatesforAday
(
      -- Add the parameters for the function here
      @DtFrom DATETIME,
      @DtTo DATETIME,
      @DayName VARCHAR(12)
)

RETURNS @DateList TABLE ([Day] varchar(20),Dt datetime)

AS
BEGIN
      IF NOT (@DayName = 'Monday' OR @DayName = 'Sunday' OR @DayName = 'Tuesday' OR @DayName = 'Wednesday' OR @DayName = 'Thursday' OR @DayName = 'Friday' OR @DayName = 'Saturday')
      BEGIN
            --Error Insert the error message and return

            INSERT INTO @DateList
            SELECT 'Invalid Day',NULL AS DAT
            RETURN
      END 

      DECLARE @TotDays INT
      DECLARE @CNT INT

      SET @TotDays =  DATEDIFF(DD,@DTFROM,@DTTO)-- [NO OF DAYS between two dates]

      SET @CNT = 0
      WHILE @TotDays >= @CNT        -- repeat for all days 
      BEGIN
        -- Pick each single day and check for the day needed
            IF DATENAME(DW, (@DTTO - @CNT)) = @DAYNAME
            BEGIN
                  INSERT INTO @DateList
                 SELECT @DAYNAME,(@DTTO - @CNT) AS DAT
            END
            SET @CNT = @CNT + 1
      END
      RETURN
END

【讨论】:

    【解决方案2】:

    此过程独立于地区和语言。

    请注意第一行SET DATEFIRST 1

    SET DATEFIRST 1; -- First day of the week is set to monday
    
    DECLARE @DateFrom DateTime ='20150601', @DateTo DateTime = '20150630' ;
    
    WITH CTE(dt)
    AS
    (
          SELECT @DateFrom
          UNION ALL
          SELECT DATEADD(d, 1, dt) FROM CTE
          WHERE dt < @DateTo
    )
    SELECT dt FROM CTE  where datepart ("dw", dt) = 1;
    

    【讨论】:

    • 注意:此解决方案使用递归,因此如果您的日期范围超过 100 天,则会失败。
    【解决方案3】:

    使用 CTE 可以通过这种方式..

    DECLARE @DateFrom DateTime ='2015-05-01',
            @DateTo DateTime = '2015-05-31'
    
    ;WITH CTE(dt)
    AS
    (
          SELECT @DateFrom
          UNION ALL
          SELECT DATEADD(d, 1, dt) FROM CTE
          WHERE dt < @DateTo
    )
    SELECT 'Monday', dt FROM CTE
    WHERE DATENAME(dw, dt) In ('Monday')
    

    【讨论】:

    • 请注意英语不是世界上唯一的语言! msdn.microsoft.com/en-us/library/ms174395.aspx -- "返回值取决于使用 SET LANGUAGE 设置的语言环境和配置登录的默认语言Server Configuration Option。"
    • 核心 SQL 语句仍然满足所提问题的目的。这个问题是用英语提出的,因此得到了回答。
    • 英语是 StackOVerflow 的交流语言。服务器可能在法国运行。
    • 日期的各种问题应该始终以一种通用的、独立于区域的方式来解决。不过,这并不容易。
    【解决方案4】:
    SET DATEFIRST 7; -- Set's sunday as first day of week, won't work otherwise
    
    DECLARE @StartDate DATE = '06/01/2015'
    
    DECLARE @EndDate DATETIME = '06/30/2015'
    
    DECLARE @TableOfDates TABLE(DateValue DATETIME)
    
    DECLARE @CurrentDate DATETIME
    
    SET @CurrentDate = @startDate
    
    WHILE @CurrentDate <= @endDate
    BEGIN
        INSERT INTO @TableOfDates(DateValue) VALUES (@CurrentDate)
    
        SET @CurrentDate = DATEADD(DAY, 1, @CurrentDate)
    END
    
    SELECT * FROM @TableOfDates WHERE DATEPART(weekday,Datevalue) = 2
    

    【讨论】:

    • sqlfiddle.com/#!6/a6bc4/3/0 我已经尝试过了,并且在日期范围内得到了正确的结果。他没有发现仅在法国服务器上运行它的任何特殊要求,他提出了一般要求。 @Alias Varghese 查看小提琴中的结果。
    • 您认为星期一是第二个工作日,但这只是美国的情况。您的示例仅适用于 SET FIRSTDATE 7 的其他地区。我对此进行了编辑,然后将删除我的反对票。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    相关资源
    最近更新 更多