Semaine ISO vs Semaine SQL Server

33

D'accord, j'ai un rapport qui fait une comparaison cette semaine par rapport à la semaine dernière et notre client a remarqué que leurs données étaient "géniales". Après un examen plus approfondi, nous avons constaté qu'il ne fonctionnait pas correctement conformément aux normes ISO. J'ai exécuté ce script en tant que test.

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

Quand couru j'ai eu ces résultats.

ResultSet

Je pensais que c'était étrange et j'ai donc creusé un peu plus et j'ai constaté que SQL Server comptait le 1er janvier comme première semaine de l'année, alors qu'ISO comptait le premier dimanche de janvier comme première semaine de l'année.

La question finit alors par être double. Question 1 pourquoi est-ce? Question 2: Y a-t-il un moyen de changer cela afin que je ne doive pas modifier tout mon code pour l'utiliser ISO_Weekpartout?

Zane
la source

Réponses:

27

À l'époque où SQL Server a implémenté la WEEKdate / partie pour la première fois, ils devaient faire un choix. Je ne pense pas qu'il y avait vraiment beaucoup de conscience à ce sujet, sauf pour s'aligner sur la norme la plus commune à l'époque - souvenez-vous que c'était à une époque où le respect des normes n'était pas une priorité absolue (sinon nous n'aurions pas timestamp, IDENTITYet TOP). Ils ont ajouté plus tard ISO_WEEK(2008, je crois) parce que la solution de contournement consistait entre-temps à écrire votre propre fichier UDF, lent et pourri, scalaire - en fait, il en a même créé un très mauvais et l'a mis dans la documentation officielle (depuis comme je peux le dire).

Je ne connais pas de moyen de faire DATEPART(WEEKsemblant DATEPART(ISO_WEEK- je pense que vous devrez changer le code (et si vous utilisez le contrôle de source, cela ne devrait pas être très difficile - combien d'endroits effectuez-vous ce calcul? vous avez pensé à l'installer quelque part afin que votre code n'ait pas à être criblé? Puisque vous changez le code maintenant, c'est peut-être le moment d'envisager cela ...).

Et si vous voulez vraiment la réponse à pourquoi? Je pense que vous devrez saisir certains des développeurs d'origine pour déterminer pourquoi ils ont choisi le paramètre par défaut qu'ils ont choisi. Encore une fois, je pense que ce n'était pas un vrai "F les normes!" choix, mais plutôt, "Quelles normes?"

Il y a quelques informations ici qui peuvent être utiles:

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
la source
Techniquement, tout ce que je devrais faire est de changer ma table DimCalendar. Malheureusement, nos développeurs ont décidé de ne pas l'utiliser dans plusieurs instances de rapport, de sorte qu'elle est calculée à la volée. En gros, il s’agissait plus d’un exercice de curiosité que de crise.
Zane
5
Je suggérerais que vos développeurs mettent à jour leurs rapports afin de suivre les meilleures pratiques plutôt que de coder les cow-boys. Mais c'est juste moi.
Aaron Bertrand
1
La bonne nouvelle est que dans moins d'une semaine, ils ne seront plus mes développeurs. :)
Zane
2

Plusieurs autorités supposent des conditions différentes pour la première semaine de l'année. Certains supposent que le premier jour de la semaine commence la première semaine, mais l'idée la plus commune est que la première semaine du premier jeudi est la première semaine de l'année.

Donc ISO_WEEKaccepte cela et comme en 2010, 2011 ou 2012, vous pouvez vérifier que le ISO_WEEK1er janvier est la 52ème ou la 53ème semaine alors que WEEKou WKou WWdit qu'ils sont la première semaine.

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Ü
la source