Получить день недели в SQL Server 2005/2008


369

Если у меня есть дата 01.01.2009, я хочу узнать, какой это был день, например, понедельник, вторник и т. Д.

Есть ли встроенная функция для этого в SQL Server 2005/2008? Или мне нужно использовать вспомогательную таблицу?


1
Если у вас есть таблица с поиском по частям даты, вы, как правило, сделали что-то не так. Функции даты в SQL Server многочисленны и надежны, поэтому любые данные, которые вам нужно извлечь из даты, можно легко сделать в столбце datetime.
Бенджамин Отин

6
вспомогательные таблицы очень полезны для вычисления даты, нет ничего необычного в том, чтобы иметь вспомогательную таблицу календаря ...

2
«Полезно для расчета даты» очень сомнительно. Большинство вычислений даты могут быть обработаны без каких-либо вспомогательных таблиц и также будут работать лучше. В некоторых случаях простая таблица Numbers выполнит эту работу - нет необходимости в таблице с действительными датами в ней. Единственная причина, по которой я увидел, что фактическая таблица календаря необходима, - это когда правила, для которых рабочие дни являются рабочими, а какие нет, являются очень сложными. То, что я видел слишком часто, - это люди, использующие таблицы дат, потому что они не знают, как это сделать другим способом. Затем они должны заполнять таблицу дат очень часто. Глупо.
ErikE

5
Я запомню свои слова, если вы покажете мне использование таблиц календаря, которые: 1) не предназначены для сложных правил праздников / рабочих дней, 2) не могут быть легко выполнены с помощью встроенных функций, и 3) только если нет # 2, таблица чисел работает так же хорошо и не требует заполнения таблицы конкретными датами.
ErikE

2
Хранилища данных широко используют таблицы календаря. Предварительно рассчитанные месяцы, кварталы, годы и т. Д. Предоставляют конечным пользователям поля, по которым они могут фильтровать / агрегировать.
Дэвид Руштон

Ответы:


694

Используйте DATENAMEили DATEPART:

SELECT DATENAME(dw,GETDATE()) -- Friday
SELECT DATEPART(dw,GETDATE()) -- 6

спасибо, что я пробовал datename но использовал d, дал мне целое число назад. dw работает как положено

39
Вот почему я предпочитаю использовать select datename (weekday, getdate ()). Мне не нужно помнить, что dw возвращает будний день .... когда я могу использовать вместо этого "будний день".
Джордж Мастрос

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

2
@niico это потому, что SQL индексирует от 1, а C подобно языкам индексирует от 0.
user824276

95

Несмотря на то, что ответ SQLMenace был принят, есть одна важная SETопция, о которой вы должны знать

SET DATEFIRST

DATENAME вернет правильное имя даты, но не то же значение DATEPART, если первый день недели был изменен, как показано ниже.

declare @DefaultDateFirst int
set @DefaultDateFirst = @@datefirst
--; 7 First day of week is "Sunday" by default
select  [@DefaultDateFirst] = @DefaultDateFirst 

set datefirst @DefaultDateFirst
select datename(dw,getdate()) -- Saturday
select datepart(dw,getdate()) -- 7

--; Set the first day of week to * TUESDAY * 
--; (some people start their week on Tuesdays...)
set datefirst 2
select datename(dw,getdate()) -- Saturday
--; Returns 5 because Saturday is the 5th day since Tuesday.
--; Tue 1, Wed 2, Th 3, Fri 4, Sat 5
select datepart(dw,getdate()) -- 5 <-- It's not 7!
set datefirst @DefaultDateFirst

33
Таким образом, чтобы получить постоянное значение datepart, вы делаете ( @@datefirst - 1 + datepart(weekday, thedate) ) % 7. Воскресенье всегда будет нулевым.
Энди Тяхджоно

1
Как бы ужасно это ни было статично, поэтому вы должны следовать оригиналу запроса, изменить значение, выполнить запрос, сбросить исходный шаблон
JonnyRaa

2
Смешная часть этого является то , что .NET в DayOfWeekперечислении имеет DayOfWeek.Sundayсо значением ... 0. Таким образом, независимо от того, что DateFirstустановлено, необработанное возвращаемое WEEKDAYзначение SQL никогда не будет совместимо с аналогом .NET. Ууу, Microsoft.
Эрик Ву

26
SELECT  CASE DATEPART(WEEKDAY,GETDATE())  
    WHEN 1 THEN 'SUNDAY' 
    WHEN 2 THEN 'MONDAY' 
    WHEN 3 THEN 'TUESDAY' 
    WHEN 4 THEN 'WEDNESDAY' 
    WHEN 5 THEN 'THURSDAY' 
    WHEN 6 THEN 'FRIDAY' 
    WHEN 7 THEN 'SATURDAY' 
END

26
Вы должны знать, что это встроенная функция для достижения того же. select datename(dw,getdate())
Сохам Дасгупта

10
@ SohamDasgupta эта встроенная функция не возвращает тот же результат для неанглийской версии MS SQL.
Мистер Скапеграс

12

Чтобы получить детерминированное значение для дня недели для данной даты, вы можете использовать комбинацию DATEPART () и @@ datefirst . В противном случае вы зависите от настроек на сервере.

Проверьте следующий сайт для лучшего решения: MS SQL: день недели

Тогда день недели будет в диапазоне от 0 до 6, где 0 - воскресенье, 1 - понедельник и т. Д. Затем вы можете использовать простую инструкцию case, чтобы вернуть правильное название дня недели.


5
Пожалуйста, поместите ответ в ответ, чтобы людям не нужно было щелкать ссылку, чтобы получить к нему ответ.
Мартин Смит,

11

ЕВРОПА:

declare @d datetime;
set @d=getdate();
set @dow=((datepart(dw,@d) + @@DATEFIRST-2) % 7+1);

2
Пожалуйста, включите объяснение того, что делает ваш код и как он отвечает на вопрос. Если в ответ вы получите фрагмент кода, вы можете не знать, что с ним делать. Ответ должен дать оператору и будущим посетителям руководство по устранению неполадок и устранению их проблем. Указание на то, что лежит в основе вашего кода, очень помогает в понимании проблемы и применении или изменении вашего решения.
Palec


3

это рабочая копия моего кода, проверьте его, как получить имя дня от даты в SQL

CREATE Procedure [dbo].[proc_GetProjectDeploymentTimeSheetData] 
@FromDate date,
@ToDate date

As 
Begin
select p.ProjectName + ' ( ' + st.Time +' '+'-'+' '+et.Time +' )' as ProjectDeatils,
datename(dw,pts.StartDate) as 'Day'
from 
ProjectTimeSheet pts 
join Projects p on pts.ProjectID=p.ID 
join Timing st on pts.StartTimingId=st.Id
join Timing et on pts.EndTimingId=et.Id
where pts.StartDate >= @FromDate
and pts.StartDate <= @ToDate
END

1

Если вы не хотите зависеть @@DATEFIRSTили использоватьDATEPART(weekday, DateColumn) , просто рассчитайте день недели самостоятельно.

Для недель по понедельникам (Европа) самое простое:

SELECT DATEDIFF(day, '17530101', DateColumn) % 7 + 1 AS MondayBasedDay

Для недели в воскресенье (Америка) используйте:

SELECT DATEDIFF(day, '17530107', DateColumn) % 7 + 1 AS SundayBasedDay

Это возвращает номер дня недели (от 1 до 7) с 1 января соответственно 7-го, 1753.


1

Вы можете использовать, DATEPART(dw, GETDATE())но имейте в виду, что результат будет зависеть от @@DATEFIRSTзначения параметра сервера SQL, которое является значением первого дня недели (в Европе значение по умолчанию 7 - воскресенье).

Если вы хотите изменить первый день недели на другое значение, вы можете использовать SET DATEFIRST но это может повлиять на всю область сеанса запросов, которая вам не нужна.

Альтернативный способ - явно указать значение первого дня недели в качестве параметра и избежать зависимости от @@DATEFIRSTнастроек. Вы можете использовать следующую формулу для достижения этой цели, когда это необходимо:

(DATEPART(dw, GETDATE()) + @@DATEFIRST + 6 - @WeekStartDay) % 7 + 1

где @WeekStartDay первый день недели, который вы хотите для своей системы (от 1 до 7, что означает с понедельника по воскресенье).

Я обернул его в функцию ниже, чтобы мы могли легко использовать его:

CREATE FUNCTION [dbo].[GetDayInWeek](@InputDateTime DATETIME, @WeekStartDay INT)
RETURNS INT
AS
BEGIN
    --Note: @WeekStartDay is number from [1 - 7] which is from Monday to Sunday
    RETURN (DATEPART(dw, @InputDateTime) + @@DATEFIRST + 6 - @WeekStartDay) % 7 + 1 
END

Пример использования: GetDayInWeek('2019-02-04 00:00:00', 1)

Это эквивалентно следующему (но не зависит от параметра DATEFIRST сервера SQL):

SET DATEFIRST 1
DATEPART(dw, '2019-02-04 00:00:00')

0

Вы можете найти эту версию полезной.

-- Test DATA
select @@datefirst
create table #test (datum datetime)
insert #test values ('2013-01-01')
insert #test values ('2013-01-02')
insert #test values ('2013-01-03')
insert #test values ('2013-01-04')
insert #test values ('2013-01-05')
insert #test values ('2013-01-06')
insert #test values ('2013-01-07')
insert #test values ('2013-01-08')
-- Test DATA

select  Substring('Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun,Mon,Tue,Wed,Thu,Fri,Sat',
        (DATEPART(WEEKDAY,datum)+@@datefirst-1)*4+1,3),Datum
        from #test 

1
Это тупой код, и он не дает никаких указаний на то, что он делает или пытается достичь
brewmanz
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.