ISO Week vs SQL Server Week

33

Oke jadi saya punya laporan yang membandingkan minggu ini vs minggu lalu dan pelanggan kami memperhatikan bahwa data mereka "funky". Setelah diselidiki lebih lanjut, kami mendapati bahwa itu tidak berjalan berminggu-minggu dengan benar sesuai dengan standar ISO. Saya menjalankan skrip ini sebagai ujian.

SET DATEFIRST 1
SELECT DATEPART(WEEK, '3/26/13')
    , DATEPART(WEEK, '3/27/12')
    , DATEPART(WEEK, '3/20/12')
    , DATEPART(WEEK, '1/2/12')
SELECT DATEPART(ISO_WEEK, '3/26/13')
    , DATEPART(ISO_WEEK, '3/27/12')
    , DATEPART(ISO_WEEK, '3/20/12')
    , DATEPART(ISO_WEEK, '1/2/12')

Saat dijalankan saya mendapat hasil ini.

Hasil Set

Saya pikir ini aneh dan jadi saya melakukan penggalian lagi dan menemukan bahwa SQL Server menghitung 1 Januari sebagai minggu pertama tahun itu di mana ISO menghitung Minggu pertama pada Januari sebagai minggu pertama tahun ini.

Pertanyaannya kemudian menjadi dua kali lipat. Pertanyaan 1 mengapa ini? Pertanyaan 2 apakah ada cara untuk mengubah ini jadi saya tidak harus mengubah semua kode saya untuk digunakan di ISO_Weekmana-mana?

Zane
sumber

Jawaban:

27

Kembali ketika SQL Server pertama kali mengimplementasikan WEEKtanggal / bagian, mereka harus membuat pilihan. Saya tidak berpikir ada banyak kesadaran tentang hal itu, kecuali untuk menyelaraskan dengan standar yang paling umum pada saat itu - ingat ini pada saat di mana menyesuaikan dengan standar bukanlah prioritas utama (kalau tidak kita tidak akan memiliki hal-hal seperti timestamp, IDENTITYdan TOP). Mereka kemudian menambahkan ISO_WEEK(2008 saya percaya) karena solusi sementara itu adalah untuk menulis UDF skalar skalar Anda sendiri yang lambat - bahkan mereka membuat yang benar-benar buruk dan memasukkannya ke dalam dokumentasi resmi (sejak itu telah dihapus sejauh ini seperti yang saya tahu).

Saya tidak tahu cara DATEPART(WEEKberpura - pura DATEPART(ISO_WEEK- saya pikir Anda harus mengubah kode (dan jika Anda menggunakan kontrol sumber, ini seharusnya tidak terlalu sulit - berapa banyak tempat Anda melakukan perhitungan ini? Anda berpikir untuk menghitungnya di suatu tempat sehingga kode Anda tidak harus penuh dengan itu? Karena Anda mengubah kode sekarang, ini mungkin waktu untuk mempertimbangkan ini ...).

Dan jika Anda benar-benar menginginkan jawaban mengapa? Saya pikir Anda harus mengambil beberapa pengembang asli untuk menentukan mengapa mereka memilih default yang mereka lakukan. Sekali lagi, saya pikir itu bukan "F standar!" pilihan, melainkan, "Standar apa?"

Ada beberapa informasi di sini yang mungkin berguna:

https://stackoverflow.com/questions/348880/getting-week-number-off-a-date-in-ms-sql-server-2005

http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/iso-week-in-sql-server

Aaron Bertrand
sumber
Secara teknis yang harus saya lakukan hanyalah mengubah tabel DimCalendar saya, sayangnya pengembang kami memutuskan untuk tidak menggunakannya dalam beberapa contoh laporan sehingga sedang dihitung saat itu juga. Pada umumnya ini lebih merupakan latihan rasa ingin tahu daripada krisis apa pun.
Zane
5
Saya sarankan Anda meminta pengembang memperbarui laporannya untuk mengikuti praktik terbaik alih-alih pengkodean koboi. Tapi itu hanya aku.
Aaron Bertrand
1
Berita baiknya adalah dalam waktu kurang dari seminggu mereka tidak akan menjadi pengembang saya lagi. :)
Zane
2

Ada beberapa otoritas dengan asumsi kondisi yang berbeda untuk minggu pertama tahun ini. Beberapa menganggap hari pertama dalam minggu itu dimulai pada minggu pertama tetapi ide yang paling umum adalah bahwa minggu pertama yang memiliki Kamis pertama adalah minggu pertama tahun itu.

Jadi ISO_WEEKmenerima itu dan seperti pada tahun 2010, 2011 atau 2012 seperti yang Anda dapat memeriksa bahwa ISO_WEEKmengatakan Januari 1 adalah 52 atau 53 minggu sementara WEEKatau WKatau WWmengatakan mereka adalah minggu pertama.

SELECT DATEPART (WW,'01/01/2010')   --> 1
SELECT DATEPART (WK,'01/01/2010')   --> 1
SELECT DATEPART (WEEK,'01/01/2010')   --> 1
SELECT DATEPART (ISO_WEEK,'01/01/2010')   --> 53
Sedat GÖÇTÜ
sumber