【问题标题】:T-SQL - Get start and end date based on week number.T-SQL - 根据周数获取开始和结束日期。
【发布时间】:2011-12-19 21:52:23
【问题描述】:

我们的业务考虑从(周一至周日)的一周。我需要编写一个 T-SQL 函数,该函数将年、周作为参数传递,它将返回该周的开始和结束日期。但是我见过很多例子,但问题在于重叠的年份。

例如 2011 年 12 月 26 日(星期一)- 2012 年 1 月 1 日(星期日)...

而且在 T-SQL 中 datepart(ww,DATE) 将星期日视为一周的开始?

或者我是不是更好地创建我自己的带有星期数的表并存储它的开始和结束日期?

【问题讨论】:

  • 您如何定义一年中的第一周?
  • 嗯,2011 年 1 月 3 日 - 2011 年 1 月 9 日。一年中的第一个星期一。
  • 您可以使用SET DATEFIRST 指定一周的开始日期。

标签: sql tsql date


【解决方案1】:
DECLARE
    @Year INT,
    @Week INT,
    @FirstDayOfYear DATETIME,
    @FirstMondayOfYear DATETIME,
    @StartDate DATETIME,
    @EndDate DATETIME

SET @Year = 2011
SET @Week = 52

-- Get the first day of the provided year.
SET @FirstDayOfYear = CAST('1/1/' + CAST(@YEAR AS VARCHAR) AS DATETIME)

-- Get the first monday of the year, then add the number of weeks.
SET @FirstMondayOfYear = DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, @FirstDayOfYear), @FirstDayOfYear)), 0)

SET @StartDate = DATEADD(WEEK, @Week - 1, @FirstMondayOfYear)

-- Set the end date to one week past the start date.
SET @EndDate = DATEADD(WEEK, 1, @StartDate)

SELECT @StartDate AS StartDate, DATEADD(SECOND, -1, @EndDate) AS EndDate

【讨论】:

  • 我认为您需要从结束日期中减去 1。经过进一步审查,我在使用第 1 周时遇到了错误的日期。
  • 周是从零开始的,但为了可用性我更新为从一开始。
  • 这不适用于 2015 年。由于某种原因,它已休假 1 周。如果是第 26 周,则显示第 27 周
【解决方案2】:

您应该创建一个表格,其中包含您不需要考虑的假期和日子。

在此之后计算初始日期和最终日期之间的天数。 (步骤1)

在您的表格中选择以检查您的初始日期和最终日期之间的天数。 (第二步)

最后用步骤1的结果减去步骤2的结果;

【讨论】:

【解决方案3】:

在这种情况下,您最好创建一个日历表:主要问题是知道要在过去/未来多长时间内填充它,但除此之外,让表架构包含周数和日期。根据您想要执行的其他基于日期的查询,您可能需要额外的列来将日期分解为其组成部分(例如,对于日/月/年/日名称等具有三个单独的列)。

【讨论】:

    【解决方案4】:

    这个怎么样:

    --DROP FUNCTION dbo.GetBusinessWeekStart
    CREATE FUNCTION dbo.GetBusinessWeekStart(
        @Year SMALLINT,
        @Week TINYINT
    )
    RETURNS DATETIME
    AS
    BEGIN
        DECLARE @FirstMonday TINYINT
        DECLARE @Result DATETIME
    
        IF ISNULL(@Week,0)<1 OR ISNULL(@Year,0)<1900
            BEGIN
                SET @Result= NULL;
            END
        ELSE
            BEGIN
                SET @FirstMonday=1
    
                WHILE DATEPART(dw,CONVERT(DATETIME, '01/0' + CONVERT(VARCHAR,@FirstMonday) + '/' + CONVERT(VARCHAR,@Year)))<>2
                BEGIN
                    SET @FirstMonday=@FirstMonday+1
                END
    
                SET @Result=CONVERT(DATETIME, '01/0' + CONVERT(VARCHAR,@FirstMonday) + '/' + CONVERT(VARCHAR,@Year))
                SET @Result=DATEADD(d,(@Week-1)*7,@Result)
    
                IF DATEPART(yyyy,@Result)<>@Year
                    BEGIN
                        SET @Result= NULL;
                    END
            END
    
        RETURN @Result
    END
    GO
    
    --Example
    SELECT dbo.GetBusinessWeekStart(2011,15) [Start],dbo.GetBusinessWeekStart(2011,15)+6 [End]
    

    【讨论】: