Uzyskaj dzień tygodnia w SQL Server 2005/2008


369

Jeśli mam datę 01.01.2009, chcę dowiedzieć się, który to był dzień, np. Poniedziałek, wtorek itp.

Czy jest w tym wbudowana funkcja SQL Server 2005/2008? Czy też muszę użyć stołu pomocniczego?


1
Jeśli masz tabelę zawierającą odnośniki do dat, ogólnie zrobiłeś coś złego. Funkcje daty programu SQL Server są liczne i niezawodne, więc wszelkie dane, które trzeba wyodrębnić z daty, można łatwo wykonać w kolumnie daty i godziny.
Benjamin Autin

6
Tabele pomocnicze są bardzo przydatne do obliczenia tej pory, nie jest niczym niezwykłym, aby mieć kalendarza stół pomocniczy ...

2
„Przydatne do obliczania daty” jest bardzo wątpliwe. Większość obliczeń dat może być obsługiwana bez żadnego dodatkowego stołu i również będzie działać lepiej. W niektórych przypadkach zwykła tabela Numbers wykona zadanie - nie ma potrzeby tabeli z faktycznymi datami. Jedynym powodem, dla którego widziałem, że potrzebna jest rzeczywista tabela kalendarza, jest to, że reguły, dla których dni są dniami roboczymi, a które dni nie są bardzo skomplikowane. Zbyt często widziałem osoby korzystające z tabel dat, ponieważ nie wiedzą, jak to zrobić w inny sposób. Następnie muszą co jakiś czas wypełniać tabelę dat. Głupi.
ErikE

5
Zjem moje słowa, jeśli możesz pokazać, że używam tabel kalendarza, które 1) nie są przeznaczone do skomplikowanych zasad dotyczących dni wolnych od pracy / dni roboczych, 2) nie można tego łatwo zrobić za pomocą wbudowanych funkcji i 3) tylko jeśli nie # 2, wtedy tabela liczb działa równie dobrze i nie wymaga zapełniania tabeli konkretnymi datami.
ErikE,

2
Hurtownie danych w szerokim zakresie wykorzystują tabele kalendarzy. Wstępnie obliczone miesiące, kwartały, lata itp. Zapewniają użytkownikom końcowym pola, według których mogą filtrować / agregować dane.
David Rushton,

Odpowiedzi:


694

Użyj DATENAMElub DATEPART:

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

Dzięki, próbowałem nazwa, ale użyłem d, dało mi liczbę całkowitą z powrotem. dw działa zgodnie z oczekiwaniami

39
Dlatego wolę używać select name (data tygodnia, getdate ()). Nie muszę pamiętać, że dw zwraca dzień tygodnia… kiedy zamiast tego mogę użyć „dnia tygodnia”.
George Mastros,

9
każdy, kto na to spojrzy - pamiętaj, że domyślnym początkiem tygodnia jest niedziela . Spójrz na odpowiedź @ Sunga, jak bezpiecznie to zmienić
JonnyRaa

2
@niico to dlatego, że indeksy SQL od 1, podczas gdy C podobnie jak indeksy języków od 0
user824276

95

Mimo że odpowiedź SQLMenace została zaakceptowana, jest jedna ważna SETopcja, o której powinieneś wiedzieć

USTAW PIERWSZĄ DATĘ

DATENAME zwróci poprawną nazwę daty, ale nie tę samą wartość DATEPART, jeśli pierwszy dzień tygodnia został zmieniony, jak pokazano poniżej.

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
Aby uzyskać stałą wartość datepart, musisz ( @@datefirst - 1 + datepart(weekday, thedate) ) % 7. Niedziela będzie zawsze zero.
Endy Tjahjono

1
okropne, że te rzeczy są statyczne, więc musisz postępować zgodnie z zapytaniem oryginalnym, zmienić wartość, uruchomić zapytanie, zresetować oryginalny wzorzec
JonnyRaa

2
Najzabawniejsze jest to, że .NET za DayOfWeekwyliczenie ma DayOfWeek.Sundayo wartości ... 0. Tak więc, bez względu na to, co DateFirstzostanie ustawione, nieprzetworzonaWEEKDAY wartość zwrócona przez SQL nigdy nie będzie zgodna z odpowiednikiem .NET. Yay, Microsoft.
Eric Wu

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
Powinieneś wiedzieć, że jest to wbudowana funkcja umożliwiająca osiągnięcie tego samego. select datename(dw,getdate())
Soham Dasgupta

10
@SohamDasgupta ta wbudowana funkcja nie zwraca tego samego wyniku dla nieanglojęzycznej wersji MS SQL.
Pan Scapegrace

12

Aby uzyskać wartość deterministyczną dla dnia tygodnia dla danej daty, można użyć kombinacji DATEPART () i @@ datefirst . W przeciwnym razie zależy to od ustawień na serwerze.

Sprawdź lepsze strony: MS SQL: Dzień tygodnia

Dzień tygodnia będzie wtedy w zakresie od 0 do 6, gdzie 0 to niedziela, 1 to poniedziałek itp. Następnie możesz użyć prostej instrukcji przypadku, aby zwrócić poprawną nazwę dnia tygodnia.


5
Proszę wpisać odpowiedź w odpowiedzi, aby ludzie nie musieli klikać linku, aby się do niej dostać.
Martin Smith,

11

EUROPA:

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

2
Dołącz wyjaśnienie tego, co robi Twój kod i jak odpowiada na pytanie. Jeśli otrzymasz fragment kodu jako odpowiedź, możesz nie wiedzieć, co z nim zrobić. Odpowiedź powinna dać OP i przyszłym odwiedzającym wskazówki, jak debugować i naprawić swój problem. Wskazanie, na czym polega Twój kod, bardzo pomaga w zrozumieniu problemu oraz zastosowaniu lub modyfikacji rozwiązania.
Palec

6

Z SQL Server 2012 i nowszymi możesz korzystać z tej FORMATfunkcji

SELECT FORMAT(GETDATE(), 'dddd')

3

to jest kopia robocza mojego kodu sprawdź, jak pobrać nazwę dnia od daty w 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

Jeśli nie chcesz polegać @@DATEFIRSTlub używać DATEPART(weekday, DateColumn), po prostu sam oblicz dzień tygodnia.

Dla tygodni opartych na poniedziałku (Europa) najprostszym jest:

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

W przypadku niedzielnych tygodni (Ameryka) użyj:

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

Zwraca liczbę dni tygodnia (od 1 do 7) od 1 stycznia odpowiednio 7, 1753.


1

Możesz użyć, DATEPART(dw, GETDATE())ale pamiętaj, że wynik będzie zależał od @@DATEFIRSTwartości ustawienia serwera SQL, która jest ustawieniem pierwszego dnia tygodnia (w Europie wartość domyślna 7, czyli niedziela).

Jeśli chcesz zmienić pierwszy dzień tygodnia na inną wartość, możesz użyć SET DATEFIRSTtej opcji, ale może to wpłynąć na wszędzie w sesji zapytania, których nie chcesz.

Alternatywnym sposobem jest jawne określenie wartości pierwszego dnia tygodnia jako parametru i unikanie tego w zależności od @@DATEFIRSTustawienia. W razie potrzeby możesz użyć następującej formuły:

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

gdzie @WeekStartDayjest pierwszy dzień tygodnia, jaki chcesz dla swojego systemu (od 1 do 7, co oznacza od poniedziałku do niedzieli).

Zawinąłem go w funkcję poniżej, abyśmy mogli go łatwo ponownie użyć:

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

Przykładowe użycie: GetDayInWeek('2019-02-04 00:00:00', 1)

Jest to równoważne z następującymi (ale niezależnymi od ustawienia DATEFIRST serwera SQL):

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

0

Ta wersja może być przydatna.

-- 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
To jest tępy kod i nie daje wskazówek co robi lub próbuje osiągnąć
brewmanz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.