Отримайте день тижня в SQL Server 2005/2008


369

Якщо у мене є дата 01.01.2009, я хочу дізнатися, який це був день, наприклад, понеділок, вівторок тощо ...

Чи є вбудована функція для цього в SQL Server 2005/2008? Або мені потрібно використовувати допоміжний стіл?


1
Якщо у вас є таблиця, що містить перегляди для порцій дати, ви, як правило, щось зробили не так. Функцій дати SQL Server багато і надійних, тому будь-які дані, які потрібно витягти з дати, можна легко зробити в стовпці дати.
Бенджамін Остін

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

2
"Корисний для розрахунків дат" є дуже сумнівним. Більшість розрахунків за дату можна обробляти без будь-якої допоміжної таблиці, і вона також буде краще. У деяких випадках звичайна таблиця чисел зробить цю роботу - немає потреби в таблиці з фактичними датами. Єдина причина, по якій я бачив, що потрібна фактична календарна таблиця, коли правила, для яких дні є робочими днями, а які - не дуже складними. Що я часто бачив - це люди, які використовують таблиці з датами, оскільки вони не знають, як це зробити іншим способом. Тоді їм доведеться заповнювати таблицю дат так часто. Нерозумно.
ErikE

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

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

Відповіді:


694

Використовуйте DATENAMEабо DATEPART:

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

THX, я спробував назву дати, але використовував d, дав мені ціле число назад. dw працює як очікувалося

39
Ось чому я вважаю за краще використовувати ім'я вибору дати (будній день, getdate ()). Мені не потрібно пам’ятати, що dw повертається будній день .... коли я можу використовувати «будній день» замість цього.
Джордж Мастрос

9
хто погляне на це - зверніть увагу, що типовим початком тижня є неділя . Подивіться на відповідь @ Sung, як це безпечно змінити
JonnyRaa

2
@niico це тому, що SQL індексує від 1, а С як мови індексує від 0.
user824276

95

Незважаючи на те, що відповідь SQLMenace була прийнята, є один важливий SETваріант, про який слід пам’ятати

СТАТИ ДАТЕФРИСТ

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
Таким чином, щоб отримати постійне значення дати, ви зробите ( @@datefirst - 1 + datepart(weekday, thedate) ) % 7. У неділю завжди буде нуль.
Endy Tjahjono

1
kindof жахливо цей матеріал є статичним, тому вам доведеться слідувати оригіналу запиту, змінити значення, запустити запит, скинути оригінальний зразок
JonnyRaa

2
Смішна частина цього є те , що .NET в DayOfWeekперерахуванні має DayOfWeek.Sundayзі значенням ... 0. Отже, незалежно від того, для чого DateFirstвстановлено, необроблене SQL повернене WEEKDAYзначення ніколи не буде сумісним з аналогом .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.
Містер Scapegrace

12

Щоб отримати детерміновану цінність дня тижня для заданої дати, ви можете використовувати комбінацію DATEPART () та @@ datefirst . Інакше ваш залежність від налаштувань на сервері.

Перегляньте наступний сайт для кращого рішення: MS SQL: День тижня

День тижня буде знаходитися в діапазоні від 0 до 6, де 0 - неділя, 1 - понеділок і т.д.


5
Будь ласка, введіть відповідь у відповідь, щоб людям не потрібно було клацати посилання, щоб дістатися до неї.
Мартін Сміт

11

ЄВРОПА:

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

2
Будь ласка, додайте пояснення того, що робить ваш код, і як він відповідає на питання. Якщо ви отримаєте фрагмент коду як відповідь, ви можете не знати, що з ним робити. Відповідь має дати керівництву ОП та майбутнім відвідувачам про те, як налагодити та вирішити свою проблему. Вказуючи, що ідея вашого коду, значно допомагає зрозуміти проблему та застосувати чи змінити своє рішення.
Палець


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 січня відповідно 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.