SQL Server UDF用于获取一周中的一周,以及第一周的参数

时间:2013-08-28 19:21:52

标签: sql sql-server datepart

我正在寻找一个等同于DATEPART(WEEK, @date)的SQL Server UDF,但允许调用者指定一周的第一天。有点类似于MySql的WEEK函数。 E.g:

CREATE FUNCTION Week (@date date, @firstdayofweek int)
RETURNS int
BEGIN
  -- return result would be the same as:
  --   SET DATEFIRST @firstdayofweek
  --   DATEPART(WEEK, @date)
END

我的申请没有机会致电SET DATEFIRST

示例:

SELECT Week('2013-08-28', 2) -- returns 35
SELECT Week('2013-08-28', 3) -- returns 36

无论SQL Server的@@DATEFIRST值如何,上述结果都将始终相同。

3 个答案:

答案 0 :(得分:0)

您可以使用以下内容:

DATEPART(WEEK, DATEADD(DAY, 8 - @firstdayofweek, @date))

而不是移动一周的第一天,而是移动实际日期。使用此公式,将使用MS SQL Server使用的天数相同的数值设置一周的第一天。 (星期日= 1,星期六= 7)

答案 1 :(得分:0)

我发现了一些文章帮助我回答了这个问题的答案:

  1. Deterministic scalar function to get week of year for a date

  2. http://sqlmag.com/t-sql/datetime-calculations-part-3

  3. 有可能简化这个UDF,但它确实给了我正在寻找的东西:

    CREATE FUNCTION Week (@date DATETIME, @dateFirst INT)
    RETURNS INT
    BEGIN
      DECLARE @normalizedWeekOfYear INT = DATEDIFF(WEEK, DATEADD(YEAR, DATEDIFF(YEAR, 0, @date), 0), @date) + 1
      DECLARE @jan1DayOfWeek INT = DATEPART(WEEKDAY, DATEADD(YEAR, DATEDIFF(YEAR, 0, @date), 0) + @@DATEFIRST- 7) - 1
      DECLARE @dateDayOfWeek INT = DATEPART(WEEKDAY, DATEADD(DAY, @@DATEFIRST- 7, @date)) - 1
    
      RETURN @normalizedWeekOfYear + 
        CASE
          WHEN @jan1DayOfWeek < @dateFirst AND @dateDayOfWeek >= @dateFirst THEN 1
          WHEN @jan1DayOfWeek >= @dateFirst AND @dateDayOfWeek < @dateFirst THEN -1
          ELSE 0
        END
    END
    GO
    

    然后,执行以下语句将分别返回35和36:

    SELECT dbo.Week('2013-08-28', 2)
    SELECT dbo.Week('2013-08-28', 3)
    

答案 2 :(得分:0)

/*
No matter how @@DATEFIRST is
return result as
weekdayName,weekdayNumber
Mo  1
Tu  2
Wn  3
Th  4
Fr  5
Sa  6
Su  7
*/

CREATE FUNCTION dbo.fnFixWeekday
(
    @currentDate date
)
RETURNS INT
AS
BEGIN
    -- get DATEFIRST setting
    DECLARE @ds int = @@DATEFIRST 
    -- get week day number under current DATEFIRST setting
    DECLARE @dow int = DATEPART(dw,@currentDate) 

    RETURN 1+(((@dow+@ds) % 7)+5) % 7

END