2013-08-28 5 views
1

Я ищу UDF SQL Server, который будет эквивалентен DATEPART(WEEK, @date), но позволит вызывающему абоненту указать первый день недели. Совсем похоже на функцию WEEK MySql. Например .:SQL Server UDF за неделю, с аргументом первого дня недели

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.

+1

Так что, если я представить 2013-08-28 и 2, что я должен вернуться? –

+0

35. Если вы отправляете 2013-08-28 и 3, вы должны вернуться назад 36. –

+0

Как насчет 2013-01-01 и 1? Кроме того, 1 представляет воскресенье или понедельник? –

ответ

0

Я нашел пару статей, которые помогли мне ответить, чтобы получить ответ на этот вопрос:

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

  2. http://sqlmag.com/t-sql/datetime-calculations-part-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) 
0

Вы могли бы использовать что-то вроде этого:

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

Вместо того чтобы двигаться в первый день недели вы двигаетесь фактическую дату. Используя эту формулу, первый день недели будет установлен с использованием тех же значений числа дней, которые использует MS SQL Server. (Воскресенье = 1, суббота = 7)

+0

Смещение дня не будет работать, потому что вы можете пересечь границу недели. Например, DATEPART (НЕДЕЛЯ, «2013-08-31») возвращает 35 (@@ DATEFIRST = 7) и DATEPART (НЕДЕЛЯ, ДАТАДЕТ (ДЕНЬ, 8 - 1, «2013-08'31»)) возвращает 36. –

+0

Извините, что ваш пример выше не ясен. Если первый день недели - 7-й день, тогда DATEPART (НЕДЕЛЯ, ДАТАДЕТ (ДЕНЬ, 8-7, «2013-08-31»)) вернет 36, потому что вы сказали, что первый день недели - суббота и 31 августа 2013 - это 36-я суббота 2013 года. Таким образом, он работает правильно. Возможно, вы пытаетесь решить другую проблему? – jellomonkey

+0

Некоторая дополнительная ясность, datepart WEEK не зависит от параметра DATEFIRST в MS SQL Server. Я не могу найти какую-либо конкретную документацию, но я ее протестировал. Неделя одинаковая, независимо от того, что происходит в первый день недели. Кроме того, я сказал, что 8-31-2013 был 36-й субботой, когда я должен был сказать, что он знаменует начало 36-й недели и фактически является 35-й субботой. – jellomonkey

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+(((@[email protected]) % 7)+5) % 7 

END 
+0

Это не отвечает на мой вопрос. Требование состоит в том, что функция должна принимать первый день недели в качестве одного из аргументов. –

Смежные вопросы