Hal yang menarik tentang DATEDIFF()
fungsi di SQL Server adalah mengabaikan SET DATEFIRST
nilai.
Namun, ini bukan bug. Dokumentasi Microsoft untuk DATEDIFF()
dengan jelas menyatakan sebagai berikut:
Menentukan
SET DATEFIRST
tidak berpengaruh padaDATEDIFF
.DATEDIFF
selalu menggunakan hari Minggu sebagai hari pertama dalam seminggu untuk memastikan fungsi beroperasi secara deterministik.
Jika Anda tidak tahu, SET DATEFIRST
menetapkan hari pertama dalam seminggu untuk sesi Anda. Ini adalah angka dari 1 hingga 7 (yang sesuai dengan Senin hingga Minggu).
Nilai awal untuk SET DATEFIRST
secara implisit diatur oleh pengaturan bahasa (yang dapat Anda atur dengan SET LANGUAGE
penyataan). Nilai sebenarnya akan tergantung pada bahasa yang disetel. Misalnya nilai default untuk us_english
bahasa 7
(Minggu), sedangkan default untuk British
bahasanya adalah 1
(Senin).
Namun, Anda dapat menggunakan SET DATEFIRST
pernyataan untuk menimpa ini sehingga Anda dapat tetap menggunakan bahasa yang sama saat menggunakan hari yang berbeda untuk hari pertama dalam seminggu.
Tapi seperti yang disebutkan, SET DATEFIRST
nilai tidak berpengaruh pada DATEDIFF()
fungsi. DATEDIFF()
fungsi selalu mengasumsikan bahwa hari Minggu adalah hari pertama dalam seminggu terlepas dari SET DATEFIRST
Anda nilai.
Ini dapat menyebabkan beberapa masalah menarik saat menggunakan DATEDIFF()
jika Anda tidak tahu cara kerjanya.
Jika Anda berada dalam situasi ini, semoga contoh di halaman ini dapat membantu.
Contoh 1 – Masalah
Pertama, inilah contoh masalah yang sebenarnya. Perhatikan bahwa kita dapat mengambil SET DATEFIRST
nilai dengan memilih @@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';
Hasil:
+------------------------+----------------------- ----------+| SET DATEFIRST Nilai | us_english TANGGAL() Hasil ||-----------------------+------------------- -------------|| 7 | 0 |+-----------------------+----------------------- ---------++-----------------------+--------------- --------------+| SET DATEFIRST Nilai | British DATEDIFF() Hasil ||-----------------------+------------------- ----------|| 1 | 0 |+-----------------------+----------------------- ------+
Dalam hal ini, kencan pertama jatuh pada hari Minggu dan kencan kedua pada hari Senin. Oleh karena itu, Anda biasanya mengharapkan DATEDIFF()
British Inggris hasil untuk mengembalikan 1
. Anda akan mengharapkan ini karena batas bagian minggu dilintasi saat berlangsung dari Minggu hingga Senin (karena SET DATEFIRST
nilainya 1
yang berarti “Senin”, dan Senin menandai awal minggu baru).
Tapi karena DATEDIFF()
mengabaikan SET DATEFIRST
nilai dan menganggap bahwa hari Minggu adalah awal minggu, kami mendapatkan hasil yang sama untuk kedua bahasa.
Untuk memastikan, saya akan menjalankan kueri lagi, tetapi kali ini saya akan mengatur SET DATEFIRST
nilai secara eksplisit . Dengan kata lain, alih-alih mengatur bahasa, saya akan menggunakan SET DATEFIRST
pernyataan:
DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06';SET DATEFIRST 7;SELECT @@DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF(minggu, @startdate, @enddate) AS 'us_english DATEDIFF() Result';SET DATEFIRST 1;SELECT @@DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF(week, @startdate, @enddate) AS 'British DATEDIFF() Result';
Hasil:
+------------------------+----------------------- ----------+| SET DATEFIRST Nilai | us_english TANGGAL() Hasil ||-----------------------+------------------- -------------|| 7 | 0 |+-----------------------+----------------------- ---------++-----------------------+--------------- --------------+| SET DATEFIRST Nilai | British DATEDIFF() Hasil ||-----------------------+------------------- ----------|| 1 | 0 |+-----------------------+----------------------- ------+
Hasil yang sama, bahkan ketika Anda secara eksplisit menyetel SET DATEFIRST
nilai. Ini tidak mengherankan – saya akan terkejut jika tidak mengembalikan hasil yang sama.
Selain itu, ini hanya mengonfirmasi bahwa DATEDIFF()
bekerja persis seperti yang dimaksudkan.
Jadi, bagaimana kita mengubahnya sehingga DATEDIFF()
. kita hasil menghormati SET DATEFIRST
. kami nilai?
Solusinya
Inilah solusi/solusi yang memungkinkan Anda mendapatkan hasil yang diinginkan. Ini akan memastikan bahwa SET DATEFIRST
pengaturan diperhitungkan ke dalam DATEDIFF()
. Anda hasil.
Yang perlu Anda lakukan adalah mengurangi @@DATEFIRST
dari tanggal input.
DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06';SET DATEFIRST 7;SELECT @@DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF(minggu, DATEADD(hari , [email protected]@DATEFIRST, @startdate), DATEADD(day, [email protected]@DATEFIRST, @enddate)) AS 'us_english DATEDIFF() Hasil';SET DATEFIRST 1;SELECT @@DATEFIRST AS 'SET DATEFIRST Nilai', DATEDIFF(minggu, DATEADD(hari, [email protected]@DATEFIRST, @tanggal mulai), DATEADD(hari, [email protected]@DATEFIRST, @tanggal akhir)) AS 'British DATEDIFF() Hasil';Hasil:
+------------------------+----------------------- ----------+| SET DATEFIRST Nilai | us_english TANGGAL() Hasil ||-----------------------+------------------- -------------|| 7 | 0 |+-----------------------+----------------------- ---------++-----------------------+--------------- --------------+| SET DATEFIRST Nilai | British DATEDIFF() Hasil ||-----------------------+------------------- ----------|| 1 | 1 |+-----------------------+----------------------- ------+Ini menggunakan
DATEADD()
berfungsi untuk mengurangi tanggal input dengan jumlah@@DATEFIRST
(yang merupakanSET DATEFIRST
. Anda nilai).Dalam hal ini
DATEDIFF()
fungsi masih menggunakan hari Minggu sebagai hari pertama dalam seminggu, namun, tanggal aktual yang digunakan dalam perhitungan berbeda. Mereka telah dipindahkan kembali ke masa lalu dengan jumlah@@DATEFIRST
.Contoh berikut menunjukkan tanggal yang digunakan dalam perhitungan:
DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06';SET DATEFIRST 7;SELECT @startdate AS 'Original Date', @@DATEFIRST SEBAGAI 'Kurangi', DATEADD(hari, [email protected]@DATEFIRST, @startdate) SEBAGAI 'Resulting Date'UNION ALLSELECT @enddate, @@DATEFIRST, DATEADD(day, [email protected]@DATEFIRST, @enddate); SET DATEFIRST 1;PILIH @startdate SEBAGAI 'Tanggal Asli', @@DATEFIRST SEBAGAI 'Kurangi Dengan', DATEADD(hari, [email protected]@DATEFIRST, @startdate) SEBAGAI 'Tanggal Hasil'UNION ALLSELECT @enddate, @@DATEFIRST , DATEADD(hari, [email protected]@DATEFIRST, @enddate);Hasil:
+-----------------+---------------+------------ ------+| Tanggal Asli | Kurangi Dengan | Tanggal Hasil ||-----------------+---------------+------------ ------|| 2025-01-05 | 7 | 2024-12-29 || 2025-01-06 | 7 | 2024-12-30 |+-------+---------------+-------- ---------++-----------------+---------------+----- -------------+| Tanggal Asli | Kurangi Dengan | Tanggal Hasil ||-----------------+---------------+------------ ------|| 2025-01-05 | 1 | 2025-01-04 || 2025-01-06 | 1 | 2025-01-05 |+-----------------+---------------+-------- ---------+Jadi dalam solusi kami,
DATEDIFF()
menggunakan "Tanggal Hasil" dalam perhitungannya.Jika Anda mengalami masalah dengan
DATEDIFF()
mengabaikanSET DATEFIRST
, semoga artikel ini membantu.