Saya mencoba mengelompokkan catatan berdasarkan minggu, menyimpan tanggal gabungan sebagai hari pertama dalam minggu itu. Namun, teknik standar yang saya gunakan untuk pembulatan tanggal tampaknya tidak bekerja dengan benar dengan minggu (meskipun untuk hari, bulan, tahun, kuartal dan jangka waktu lain yang telah saya terapkan).
Inilah SQL-nya:
select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), 0);
Ini kembali 2011-08-22 00:00:00.000
, yang merupakan hari Senin, bukan hari Minggu. Memilih @@datefirst
kembali 7
, yang merupakan kode untuk hari Minggu, sehingga server diatur dengan benar sejauh yang saya tahu.
Saya dapat melewati ini dengan cukup mudah dengan mengubah kode di atas menjadi:
select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), -1);
Tetapi fakta bahwa saya harus membuat pengecualian seperti itu membuat saya sedikit tidak nyaman. Juga, mohon maaf jika ini adalah pertanyaan duplikat. Saya menemukan beberapa pertanyaan terkait tetapi tidak ada yang membahas aspek ini secara khusus.
sumber
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7
tetap konstan terlepas dari@@datefirst
pengaturan saya pikir. Dengan Senin = 2.Jawaban:
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, ... sepertiDATEDIFF
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:Untuk menjawab bagaimana mendapatkan hari Minggu:
Jika Anda menginginkan hari Minggu, pilih tanggal dasar yang bukan hari Senin melainkan hari Minggu. Sebagai contoh:
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 padaDATEFIRST
pengaturan, misalnyaJadi 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:...atau...
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":
Kueri tugas "Mahal":
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.
sumber
Untuk ini yang perlu mendapatkan:
Senin = 1 dan Minggu = 7:
Minggu = 1 dan Sabtu = 7:
Di atas ada contoh serupa, tapi berkat menggandakan "% 7" itu akan jauh lebih lambat.
sumber
select (datediff(dd,5,cal.D_DATE)%7 + 1)
danselect (datediff(dd,6,cal.D_DATE)%7 + 1)
Bagi mereka yang membutuhkan jawaban di tempat kerja dan membuat fungsi dilarang oleh DBA Anda, solusi berikut ini akan berfungsi:
Ini menunjukkan awal minggu itu. Di sini saya berasumsi bahwa hari Minggu adalah awal minggu. Jika menurut Anda hari Senin adalah permulaan, Anda harus menggunakan:
sumber
Ini bekerja sangat baik untuk saya:
sumber
Googled skrip ini:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307
sumber
Mungkin Anda membutuhkan ini:
Atau
Fungsi
sumber
DATEPART(DW
tergantung pada@@datefirst
DATE
maka Anda tidak perlu melakukan konversi sub-optimal keVARCHAR
dan kembali hanya untuk menghapus komponen waktu tidak disengaja yang lewat.Time
nilai.sumber
Untuk dasar (Minggu minggu ini)
Jika minggu sebelumnya:
Secara internal, kami membangun fungsi yang melakukannya tetapi jika Anda perlu cepat dan kotor, ini akan melakukannya.
sumber
Karena tanggal Julian 0 adalah hari Senin tambahkan saja jumlah minggu ke hari Minggu yang merupakan hari sebelum -1 Misalnya. pilih dateadd (wk, tanggaliff (wk, 0, getdate ()), - 1)
sumber
Ini logika saya. Tetapkan hari pertama minggu menjadi Senin lalu hitung hari apa dalam seminggu untuk hari pemberian, kemudian menggunakan DateAdd dan Kasus Saya menghitung tanggal berapa pada hari Senin sebelumnya minggu itu.
sumber
Saya tidak memiliki masalah dengan jawaban yang diberikan di sini, namun menurut saya jawaban saya jauh lebih sederhana untuk diterapkan, dan dipahami. Saya belum menjalankan tes kinerja apa pun padanya, tetapi itu harus dapat diabaikan.
Jadi saya mendapatkan jawaban saya dari fakta bahwa tanggal disimpan di SQL server sebagai bilangan bulat, (saya berbicara tentang komponen tanggal saja). Jika Anda tidak percaya, coba SELECT CONVERT (INT, GETDATE ()) ini, dan sebaliknya.
Sekarang mengetahui hal ini, Anda dapat melakukan beberapa persamaan matematika yang keren. Anda mungkin bisa mendapatkan yang lebih baik, tapi ini milik saya.
sumber
@@DATEFIRST
juga 7, tetapi jika Anda@testDate
adalah awal minggu ini, maka ini mengembalikan tanggal pada hari sebelumnya.Saya punya masalah serupa. Diberikan tanggal, saya ingin mendapatkan tanggal Senin minggu itu.
Saya menggunakan logika berikut: Temukan nomor hari dalam minggu dalam kisaran 0-6, lalu kurangi dari tanggal awal.
Saya menggunakan: DATEADD (hari, - (DATEPART (hari kerja,) + 5)% 7,)
Karena DATEPRRT (hari kerja,) mengembalikan 1 = Minggu ... 7 = Sabtu, DATEPART (hari kerja,) + 5)% 7 mengembalikan 0 = Senin ... 6 = Minggu.
Pengurangan jumlah hari ini dari tanggal asli menghasilkan hari Senin sebelumnya. Teknik yang sama dapat digunakan untuk setiap hari awal dalam seminggu.
sumber
Saya menemukan ini sederhana dan berguna. Bekerja meskipun hari pertama dalam seminggu adalah Minggu atau Senin.
MENYATAKAN @BaseDate SEBAGAI Tanggal
SET @BaseDate = GETDATE ()
MENYATAKAN @FisrtDOW SEBAGAI Tanggal
SELECT @FirstDOW = DATEADD (d, DATEPART (WEEKDAY, @ BaseDate) * -1 + 1, @BaseDate)
sumber
Mungkin saya terlalu menyederhanakan di sini, dan mungkin itu masalahnya, tetapi tampaknya ini berhasil untuk saya. Belum mengalami masalah dengan itu ...
sumber
SET DATEFIRST
.DATEFIRST
sama sekali (selama tiga setengah tahun sekarang), dan tetap tidak. Dan Anda juga harus menghindari format regional sepertim/d/y
, bahkan dalam skenario di mana m dan d sama.