2013-05-14 19 views
3

Я искал вокруг кусок кода, чтобы найти первый день текущей недели, и везде я смотрю я вижу это:SQL Server - Нахождение первого дня недели

DATEADD(WK, DATEDIFF(WK,0,GETDATE()),0) 

Каждый место говорит, что это код, который я ищу.

Проблема с этим фрагментом кода заключается в том, что если вы запустите его в воскресенье, он выберет следующий понедельник.


Если я бег:

SELECT GetDate() , DATEADD(WK, DATEDIFF(WK,0,GETDATE()),0) 

Результатов на сегодня (вторник):

2013-05-14 09:36:39.650................2013-05-13 00:00:00.000 

Это правильно, он выбирает в понедельник 13-го.


Если я бегу:

SELECT GetDate()-1 , DATEADD(WK, DATEDIFF(WK,0,GETDATE()-1),0) 

результаты за вчера (понедельник):

2013-05-13 09:38:57.950................2013-05-13 00:00:00.000 

Это правильно, он выбирает в понедельник 13-го.


Если я бегу:

SELECT GetDate()-2 , DATEADD(WK, DATEDIFF(WK,0,GETDATE()-2),0) 

Результаты по 12 (воскресенье):

2013-05-12 09:40:14.817................2013-05-13 00:00:00.000 

Это не правильно, он выбирает в понедельник 13-го, когда он должен выбрать предыдущий понедельник , 6-й.

Может ли кто-нибудь осветить меня относительно того, что здесь происходит? Мне трудно поверить, что никто не указал, что это не работает, поэтому мне интересно, чего я не хватает.

+0

I верьте, что корень проблемы - использование даты 0, которая в SQL Server разрешает «1900-01-01» - это был понедельник. –

+1

Возможный дубликат [Получить первый день недели в SQL Server] (http://stackoverflow.com/questions/7168874/get-first-day-of-week-in-sql-server) – Pondlife

+1

@Pondlife: Не совсем. Проблема в том, почему разные понедельники возвращаются в зависимости от даты или воскресенья или любого другого дня недели. –

ответ

4

Попробуйте этот -

SET DATEFIRST 1 

DECLARE @Date DATETIME 
SELECT @Date = GETDATE() 

SELECT CAST(DATEADD(DAY, 1 - DATEPART(WEEKDAY, @Date), @Date) AS DATE) 

SELECT CAST(@Date - 2 AS DATE), CAST(DATEADD(WK, DATEDIFF(WK, 0, @Date-2), 0) AS DATE) 

Результаты:

---------- ---------- 
2013-05-12 2013-05-13 
2

SQL Server имеет SET DATEFIRST функцию, которая позволяет вам сказать это то, что первый день недели должно быть. SET DATEFIRST = 1 говорит, что он рассматривает понедельник как первый день недели. Вы должны проверить настройки сервера по умолчанию: @@ DATEFIRST. Или вы можете просто изменить его в начале вашего запроса.

Некоторые ссылки:

MSDN

Similar Question

+0

DATEDIFF (WEEK) игнорирует настройку DATEFIRST, и поэтому неправильный понедельник возвращается в воскресенье (когда @@ DATEFIRST = 1). –

4

Это DATEDIFF, что возвращает «неправильный» разница недель, что в конце концов приводит к неправильному понедельник.И это потому, что DATEDIFF(WEEK, ...) не учитывает настройку DATEFIRST, которую я предполагаю, что вы установили значение 1 (понедельник), и вместо этого всегда считает, что переход недели с субботы на воскресенье или, другими словами, он безоговорочно считает Воскресенье является первый день недели в этом контексте.

Что касается объяснения , что, до сих пор я не смог найти официальный один, но я считаю, что это должно быть что-то делать с функцией DATEDIFF является одним из тех угощениями SQL Server как always deterministic. По-видимому, если DATEDIFF(WEEK, ...) полагался на DATEFIRST, его больше нельзя было считать всегда детерминированным, о котором я могу только догадываться не было, как этого хотели разработчики SQL Server.

Чтобы найти первый день дня в неделю, я бы (и наиболее часто на самом деле) использовать первое предложение в @Jasmina Shevchenko's answer:

DATEADD(DAY, 1 - DATEPART(WEEKDAY, @Date), @Date) 

DATEPART действительно уважает установку DATEFIRST и (скорее всего, в результате) он отсутствует в списке всегда детерминированный функции.

0

Это работало для меня как шарм:

Установка Moday в первый день недели, не меняя DATEFIRST переменную:

-- FirstDayWeek  
select dateadd(dd,(datepart(dw, case datepart(dw, [yourDate]) when 1 then dateadd(dd,-1,[yourDate]) else [yourDate] end) * -1) + 2, case datepart(dw, [yourDate]) when 1 then dateadd(dd,-1,[yourDate]) else [yourDate] end) as FirstDayWeek; 

-- LastDayWeek 
select dateadd(dd, (case datepart(dw, [yourDate]) when 1 then datepart(dw, dateadd(dd,-1,[yourDate])) else datepart(dw, [yourDate]) end * -1) + 8, case datepart(dw, [yourDate]) when 1 then dateadd(dd,-1,[yourDate]) else [yourDate] end) as LastDayWeek; 

Настройка воскресенье, как кулак день недели без изменения DATEFIRST переменной

select convert(varchar(50), dateadd(dd, (datepart(dw, [yourDate]) * -1) + 2, [yourDate]), 103) as FirstDayWeek, convert(varchar(50), dateadd(dd, (datepart(dw, [yourDate]) * -1) + 8, [yourDate]), 103) as LastDayWeek; 

Вы можете изменить [yourDate] по GETDATE() для тестирования