Untuk menjawab mengapa Anda mendapatkan hari Senin dan bukan hari Minggu:
Anda menambahkan beberapa minggu ke tanggal 0. Apakah tanggal 0 itu? 1900-01-01. Hari apa pada 01-01-2019? Senin. Jadi dalam kode Anda, Anda mengatakan, berapa minggu telah berlalu sejak Senin, 1 Januari 1900? Sebut saja itu [n]. Oke, sekarang tambahkan [n] minggu ke Senin, 1 Januari 1900. Anda tidak perlu heran bahwa ini akhirnya menjadi hari Senin. DATEADD
tidak tahu ingin menambah minggu tetapi hanya sampai anda mendapatkan hari minggu, itu hanya menambahkan 7 hari, kemudian menambahkan 7 hari lagi, ... seperti DATEDIFF
hanya mengenali batas-batas yang telah dilintasi. Misalnya, keduanya mengembalikan 1, meskipun beberapa orang mengeluh bahwa seharusnya ada beberapa logika yang masuk akal yang dibangun untuk membulatkan ke atas atau ke bawah:
SELECT DATEDIFF(YEAR, '2010-01-01', '2011-12-31');
SELECT DATEDIFF(YEAR, '2010-12-31', '2011-01-01');
Untuk menjawab bagaimana mendapatkan hari Minggu:
Jika Anda menginginkan hari Minggu, pilih tanggal dasar yang bukan hari Senin melainkan hari Minggu. Sebagai contoh:
DECLARE @dt DATE = '1905-01-01';
SELECT [start_of_week] = DATEADD(WEEK, DATEDIFF(WEEK, @dt, CURRENT_TIMESTAMP), @dt);
Ini tidak akan rusak jika Anda mengubah DATEFIRST
setelan Anda (atau kode Anda dijalankan untuk pengguna dengan setelan berbeda) - asalkan Anda masih menginginkan hari Minggu terlepas dari setelan saat ini. Jika Anda ingin dua jawaban jive, maka Anda harus menggunakan fungsi yang tidak bergantung pada DATEFIRST
pengaturan, misalnya
SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
Jadi jika Anda mengubah DATEFIRST
pengaturan Anda menjadi Senin, Selasa, apa pun yang Anda, perilakunya akan berubah. Bergantung pada perilaku yang Anda inginkan, Anda dapat menggunakan salah satu fungsi berikut:
CREATE FUNCTION dbo.StartOfWeek1 -- always a Sunday
(
@d DATE
)
RETURNS DATE
AS
BEGIN
RETURN (SELECT DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @d), '19050101'));
END
GO
...atau...
CREATE FUNCTION dbo.StartOfWeek2 -- always the DATEFIRST weekday
(
@d DATE
)
RETURNS DATE
AS
BEGIN
RETURN (SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, @d), @d));
END
GO
Sekarang, Anda memiliki banyak alternatif, tetapi mana yang berkinerja terbaik? Saya akan terkejut jika akan ada perbedaan besar tetapi saya mengumpulkan semua jawaban yang diberikan sejauh ini dan menjalankannya melalui dua rangkaian tes - satu murah dan satu mahal. Saya mengukur statistik klien karena saya tidak melihat I / O atau memori berperan dalam kinerja di sini (meskipun itu mungkin ikut bermain tergantung pada bagaimana fungsi digunakan). Dalam pengujian saya, hasilnya adalah:
Kueri tugas "murah":
Function - client processing time / wait time on server replies / total exec time
Gandarez - 330/2029/2359 - 0:23.6
me datefirst - 329/2123/2452 - 0:24.5
me Sunday - 357/2158/2515 - 0:25.2
trailmax - 364/2160/2524 - 0:25.2
Curt - 424/2202/2626 - 0:26.3
Kueri tugas "Mahal":
Function - client processing time / wait time on server replies / total exec time
Curt - 1003/134158/135054 - 2:15
Gandarez - 957/142919/143876 - 2:24
me Sunday - 932/166817/165885 - 2:47
me datefirst - 939/171698/172637 - 2:53
trailmax - 958/173174/174132 - 2:54
Saya dapat menyampaikan detail pengujian saya jika diinginkan - berhenti di sini karena ini sudah cukup bertele-tele. Saya sedikit terkejut melihat Curt keluar sebagai yang tercepat di kelas atas, mengingat jumlah perhitungan dan kode sebaris. Mungkin saya akan menjalankan beberapa tes dan blog yang lebih menyeluruh tentang itu ... jika kalian tidak keberatan saya menerbitkan fungsi Anda di tempat lain.
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7
tetap konstan terlepas dari@@datefirst
pengaturan saya pikir. Dengan Senin = 2.