Получить день недели в 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.