ISO-Woche vs SQL Server-Woche

33

Okay, ich habe einen Bericht, der einen Vergleich zwischen dieser Woche und der letzten Woche macht, und unser Kunde hat bemerkt, dass seine Daten "funky" waren. Bei weiteren Untersuchungen stellten wir fest, dass es nach den ISO-Standards wochenlang nicht richtig lief. Ich habe dieses Skript als Testfall ausgeführt.

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')

Beim Laufen habe ich diese Ergebnisse erhalten.

ResultSet

Ich fand das merkwürdig und machte einige weitere Grabungen. Dabei stellte ich fest, dass SQL Server den 1. Januar als erste Woche des Jahres zählt, während ISO den ersten Sonntag im Januar als erste Woche des Jahres zählt.

Die Frage ist dann zweifach. Frage 1 warum ist das so? Frage 2: Gibt es eine Möglichkeit, dies zu ändern, damit ich nicht meinen gesamten Code ändern muss, um ihn ISO_Weeküberall zu verwenden ?

Zane
quelle

Antworten:

27

Als SQL Server das WEEKDatum / den Teil zum ersten Mal implementierte , mussten sie eine Auswahl treffen. Ich glaube nicht, dass es wirklich viel Bewusstsein gab, außer, dass wir uns dem gängigsten Standard zu dieser Zeit angeglichen haben. Denken Sie daran, dass dies zu einer Zeit war, in der die Konformität mit den Standards nicht oberste Priorität hatte (sonst hätten wir keine Dinge wie timestamp, IDENTITYund TOP). Sie haben später hinzugefügt ISO_WEEK(glaube ich 2008), weil die Problemumgehung in der Zwischenzeit darin bestand, Ihre eigene, langsame, beschissene Skalar-UDF zu schreiben - tatsächlich haben sie sogar eine wirklich schlechte erstellt und in die offizielle Dokumentation aufgenommen (sie wurde inzwischen so weit entfernt) wie ich sagen kann).

Ich kenne keine Möglichkeit, dies so zu DATEPART(WEEKtun DATEPART(ISO_WEEK, als müssten Sie den Code ändern (und wenn Sie die Quellcodeverwaltung verwenden, sollte dies nicht sehr schwierig sein - an wie vielen Stellen führen Sie diese Berechnung durch? Sie haben darüber nachgedacht, den Code irgendwo zu berechnen, damit Sie sich nicht damit herumärgern müssen? Da Sie den Code jetzt ändern, ist es möglicherweise an der Zeit, dies zu berücksichtigen ...).

Und wenn Sie wirklich die Antwort auf warum wollen? Ich denke, Sie müssen einige der ursprünglichen Entwickler zu Rate ziehen, um herauszufinden, warum sie die Standardeinstellung gewählt haben, die sie verwendet haben. Auch hier denke ich, dass es kein "F the Standards" war! Wahl, sondern "Welche Standards?"

Hier finden Sie einige nützliche Informationen:

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
quelle
Eigentlich müsste ich nur meine DimCalendar-Tabelle ändern. Leider haben unsere Entwickler beschlossen, sie nicht in mehreren Berichtsinstanzen zu verwenden, damit sie sofort berechnet wird. Im Großen und Ganzen war dies eher eine Übung der Neugier als eine Krise.
Zane
5
Ich würde vorschlagen, dass Ihre Entwickler ihre Berichte aktualisieren, um Best Practices zu befolgen, anstatt Cowboy-Codierung. Aber das bin nur ich.
Aaron Bertrand
1
Die gute Nachricht ist, dass sie in weniger als einer Woche nicht mehr meine Entwickler sein werden. :)
Zane
2

In der ersten Woche des Jahres gehen mehrere Behörden von unterschiedlichen Bedingungen aus. Einige gehen davon aus, dass der erste Wochentag mit der ersten Woche beginnt, aber die häufigste Idee ist, dass die erste Woche mit dem ersten Donnerstag die erste Woche des Jahres ist.

So ISO_WEEKakzeptiert , dass und wie in 2010, 2011 oder 2012 , wie Sie können überprüfen , dass ISO_WEEKsagt 1. Januar ist der 52. oder der 53. Woche , während WEEKoder WKoder WWsagt , dass sie in der ersten Woche sind.

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Ü
quelle