Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Obejście dla DATEDIFF() Ignorowanie SET DATEFIRST w SQL Server (przykład T-SQL)

Ciekawa rzecz o DATEDIFF() funkcji w SQL Server jest to, że ignoruje twój SET DATEFIRST wartość.

Nie jest to jednak błąd. Dokumentacja Microsoft dla DATEDIFF() wyraźnie stwierdza, co następuje:

Określanie SET DATEFIRST nie ma wpływu na DATEDIFF . DATEDIFF zawsze używa niedzieli jako pierwszego dnia tygodnia, aby zapewnić, że funkcja działa w sposób deterministyczny.

Jeśli nie wiesz, SET DATEFIRST ustawia pierwszy dzień tygodnia dla Twojej sesji. To liczba od 1 do 7 (co odpowiada od poniedziałku do niedzieli).

Początkowa wartość dla SET DATEFIRST jest domyślnie ustawiana przez ustawienie języka (które można ustawić za pomocą SET LANGUAGE oświadczenie). Rzeczywista wartość będzie zależeć od ustawionego języka. Na przykład domyślna wartość dla us_english język to 7 (niedziela), podczas gdy ustawienie domyślne dla British język to 1 (Poniedziałek).

Możesz jednak użyć SET DATEFIRST oświadczenie, aby zastąpić to, aby można było używać tego samego języka, używając innego dnia pierwszego dnia tygodnia.

Ale jak wspomniano, SET DATEFIRST wartość nie ma wpływu na DATEDIFF() funkcjonować. DATEDIFF() funkcja zawsze zakłada, że ​​niedziela jest pierwszym dniem tygodnia, niezależnie od Twojego SET DATEFIRST wartość.

Może to powodować interesujące problemy podczas używania DATEDIFF() jeśli nie wiesz, jak to działa.

Jeśli znajdziesz się w takiej sytuacji, mam nadzieję, że przykłady na tej stronie mogą pomóc.

Przykład 1 – Problem

Po pierwsze, oto przykład rzeczywistego problemu. Zauważ, że możemy pobrać SET DATEFIRST wartość, wybierając @@DATEFIRST .

DECLARE 
  @startdate date = '2025-01-05', 
  @enddate date = '2025-01-06';

SET LANGUAGE us_english;
SELECT 
  @@DATEFIRST AS 'SET DATEFIRST Value', 
  DATEDIFF(week, @startdate, @enddate) AS 'us_english DATEDIFF() Result';

SET LANGUAGE British;
SELECT 
  @@DATEFIRST AS 'SET DATEFIRST Value', 
  DATEDIFF(week, @startdate, @enddate) AS 'British DATEDIFF() Result';

Wynik:

+-----------------------+--------------------------------+
| SET DATEFIRST Value   | us_english DATEDIFF() Result   |
|-----------------------+--------------------------------|
| 7                     | 0                              |
+-----------------------+--------------------------------+

+-----------------------+-----------------------------+
| SET DATEFIRST Value   | British DATEDIFF() Result   |
|-----------------------+-----------------------------|
| 1                     | 0                           |
+-----------------------+-----------------------------+

W tym przypadku pierwsza data wypada w niedzielę, a druga w poniedziałek. Dlatego normalnie można by się spodziewać brytyjskiego DATEDIFF() wynik do zwrócenia 1 . Można się tego spodziewać, ponieważ granica części tygodnia jest przekraczana, gdy przechodzi od niedzieli do poniedziałku (ponieważ SET DATEFIRST wartość to 1 co oznacza „poniedziałek”, a poniedziałek oznacza początek nowego tygodnia).

Ale ponieważ DATEDIFF() ignoruje Twój SET DATEFIRST i przy założeniu, że niedziela jest początkiem tygodnia, otrzymujemy ten sam wynik dla obu języków.

Dla pewności ponownie uruchomię zapytanie, ale tym razem ustawię SET DATEFIRST wartość wyraźnie . Innymi słowy, zamiast ustawiać język, użyję SET DATEFIRST oświadczenie:

DECLARE 
  @startdate date = '2025-01-05', 
  @enddate date = '2025-01-06';

SET DATEFIRST 7;
SELECT 
  @@DATEFIRST AS 'SET DATEFIRST Value', 
  DATEDIFF(week, @startdate, @enddate) AS 'us_english DATEDIFF() Result';

SET DATEFIRST 1;
SELECT 
  @@DATEFIRST AS 'SET DATEFIRST Value', 
  DATEDIFF(week, @startdate, @enddate) AS 'British DATEDIFF() Result';

Wynik:

+-----------------------+--------------------------------+
| SET DATEFIRST Value   | us_english DATEDIFF() Result   |
|-----------------------+--------------------------------|
| 7                     | 0                              |
+-----------------------+--------------------------------+

+-----------------------+-----------------------------+
| SET DATEFIRST Value   | British DATEDIFF() Result   |
|-----------------------+-----------------------------|
| 1                     | 0                           |
+-----------------------+-----------------------------+

Ten sam wynik, nawet jeśli jawnie ustawisz SET DATEFIRST wartość. Nie jest to jednak niespodzianka – byłbym zaskoczony, gdyby nie zwróć ten sam wynik.

To po prostu potwierdza, że ​​DATEDIFF() działa dokładnie zgodnie z przeznaczeniem.

Jak więc to zmienić, aby nasza DATEDIFF() wyniki honorują nasz SET DATEFIRST wartość?

Rozwiązanie

Oto rozwiązanie/obejście, które pozwoli Ci uzyskać zamierzone rezultaty. Zapewni to, że Twój SET DATEFIRST ustawienia są uwzględniane w DATEDIFF() wyniki.

Wystarczy odjąć @@DATEFIRST od dat wejściowych.

DECLARE 
  @startdate date = '2025-01-05', 
  @enddate date = '2025-01-06';

SET DATEFIRST 7;
SELECT 
  @@DATEFIRST AS 'SET DATEFIRST Value', 
  DATEDIFF(week, DATEADD(day, [email protected]@DATEFIRST, @startdate), DATEADD(day, [email protected]@DATEFIRST, @enddate)) AS 'us_english DATEDIFF() Result';

SET DATEFIRST 1;
SELECT 
  @@DATEFIRST AS 'SET DATEFIRST Value', 
  DATEDIFF(week, DATEADD(day, [email protected]@DATEFIRST, @startdate), DATEADD(day, [email protected]@DATEFIRST, @enddate)) AS 'British DATEDIFF() Result';

Wynik:

+-----------------------+--------------------------------+
| SET DATEFIRST Value   | us_english DATEDIFF() Result   |
|-----------------------+--------------------------------|
| 7                     | 0                              |
+-----------------------+--------------------------------+

+-----------------------+-----------------------------+
| SET DATEFIRST Value   | British DATEDIFF() Result   |
|-----------------------+-----------------------------|
| 1                     | 1                           |
+-----------------------+-----------------------------+

Używa DATEADD() funkcja zmniejszania wprowadzonych dat o ilość @@DATEFIRST (który jest twoim SET DATEFIRST wartość).

W tym przypadku DATEDIFF() funkcja nadal używa niedzieli jako pierwszego dnia tygodnia, jednak rzeczywiste daty użyte w obliczeniach są różne. Zostały przesunięte w czasie o @@DATEFIRST .

Poniższy przykład pokazuje daty użyte w obliczeniach:

DECLARE 
  @startdate date = '2025-01-05', 
  @enddate date = '2025-01-06';

SET DATEFIRST 7;
SELECT 
  @startdate AS 'Original Date', 
  @@DATEFIRST AS 'Subtract By',
  DATEADD(day, [email protected]@DATEFIRST, @startdate) AS 'Resulting Date'
UNION ALL
SELECT 
  @enddate, 
  @@DATEFIRST,
  DATEADD(day, [email protected]@DATEFIRST, @enddate);  

SET DATEFIRST 1;
SELECT 
  @startdate AS 'Original Date', 
  @@DATEFIRST AS 'Subtract By',
  DATEADD(day, [email protected]@DATEFIRST, @startdate) AS 'Resulting Date'
UNION ALL
SELECT 
  @enddate, 
  @@DATEFIRST,
  DATEADD(day, [email protected]@DATEFIRST, @enddate);  

Wynik:

+-----------------+---------------+------------------+
| Original Date   | Subtract By   | Resulting Date   |
|-----------------+---------------+------------------|
| 2025-01-05      | 7             | 2024-12-29       |
| 2025-01-06      | 7             | 2024-12-30       |
+-----------------+---------------+------------------+

+-----------------+---------------+------------------+
| Original Date   | Subtract By   | Resulting Date   |
|-----------------+---------------+------------------|
| 2025-01-05      | 1             | 2025-01-04       |
| 2025-01-06      | 1             | 2025-01-05       |
+-----------------+---------------+------------------+

W naszym obejściu DATEDIFF() wykorzystał w swoich obliczeniach „Datę Wyniku”.

Jeśli masz problemy z DATEDIFF() ignorowanie SET DATEFIRST , miejmy nadzieję, że ten artykuł pomógł.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 4 sposoby, aby dowiedzieć się, jakie kolumny zostaną zwrócone przez procedurę składowaną w SQL Server

  2. Chcę użyć instrukcji CASE do aktualizacji niektórych rekordów w serwerze sql 2005

  3. Przywracanie głównej bazy danych programu SQL Server

  4. SQL Server - podsłuchiwanie parametrów

  5. Rozwiązywanie problemów z wydajnością procesora SQL Server