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?

koń bez imienia
źródło
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
SQLMenace
źródło
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
dance2die
źródło
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
Sutirth
źródło
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.

lazerwire.com
źródło
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);
npg
źródło
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')
Chris Stillwell
źródło
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
Tapan Kumar
źródło
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.

Michel de Ruiter
źródło
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')
Minh Nguyen
źródło
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 
Reto
źródło
1
To jest tępy kod i nie daje wskazówek co robi lub próbuje osiągnąć
brewmanz