简体   繁体   English

SQL Server UDF用于获取一年的第几周,并带有“一周的第一天”参数

[英]SQL Server UDF for getting week of year, with first day of week argument

I'm looking for a SQL Server UDF that will be equivalent to DATEPART(WEEK, @date) , but will allow the caller to specify the first day of the week. 我正在寻找与DATEPART(WEEK, @date)等效的SQL Server UDF,但允许调用者指定一周的第一天。 Somewhat similar to MySql's WEEK function. 有点类似于MySql的WEEK函数。 Eg: 例如:

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

My application does not have the opportunity to call SET DATEFIRST . 我的应用程序没有机会调用SET DATEFIRST

Examples: 例子:

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

The above results would always be the same, regardless of SQL Server's value for @@DATEFIRST . 不管SQL Server的@@DATEFIRST值如何,以上结果始终是相同的。

You could use something like this: 您可以使用如下形式:

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

Instead of moving the first day of the week you are moving the actual date. 您无需移动星期的第一天,而是移动实际的日期。 Using this formula the first day of the week would be set using the same number values for days that MS SQL Server uses. 使用此公式,将使用与MS SQL Server使用的天相同的数字值来设置一周的第一天。 (Sunday = 1, Saturday = 7) (星期日= 1,星期六= 7)

I've found a couple of articles that helped me answer to derive an answer to this question: 我找到了几篇文章来帮助我回答这个问题的答案:

  1. Deterministic scalar function to get week of year for a date 确定性标量函数以获取日期中的星期

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

It may be possible to simplify this UDF, but it gives me exactly what I was looking for: 可能可以简化此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

Then, executing the following statements would return 35 and 36 respectively: 然后,执行以下语句将分别返回35和36:

SELECT dbo.Week('2013-08-28', 2)
SELECT dbo.Week('2013-08-28', 3)
/*
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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM