Semana ISO x Semana do SQL Server

33

Ok, então eu tenho um relatório que faz uma comparação desta semana com a semana passada e nosso cliente percebeu que seus dados estavam "descolados". Após uma investigação mais aprofundada, descobrimos que as semanas não estavam funcionando corretamente de acordo com os padrões ISO. Eu executei esse script como um caso de teste.

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

Quando executado, obtive esses resultados.

ResultSet

Eu pensei que isso era peculiar e, portanto, fiz mais algumas pesquisas e descobri que o SQL Server conta em 1º de janeiro como a primeira semana do ano em que a ISO conta no primeiro domingo de janeiro como a primeira semana do ano.

A questão acaba sendo duas vezes. Pergunta 1 por que isso? Pergunta 2: existe alguma maneira de mudar isso, para que eu não precise modificar todo o meu código para usar em ISO_Weekqualquer lugar?

Zane
fonte

Respostas:

27

Quando o SQL Server implementou a WEEKdata / peça pela primeira vez, eles tiveram que fazer uma escolha. Acho que não havia muita consciência disso, exceto para alinhar com o padrão mais comum na época - lembre-se de que era um momento em que a conformidade com os padrões não era uma prioridade (caso contrário, não teríamos coisas como timestamp, IDENTITYe TOP). Mais tarde, eles acrescentaram ISO_WEEK(eu acredito em 2008) porque a solução alternativa foi escrever sua própria UDF escalar lenta e de baixa qualidade - na verdade, eles criaram uma realmente ruim e a colocaram na documentação oficial (desde então, ela foi removida até agora). como eu posso dizer).

Não sei como DATEPART(WEEKfingir que é DATEPART(ISO_WEEK- acho que você precisará alterar o código (e se estiver usando o controle de origem, isso não deve ser muito difícil - em quantos lugares você está realizando esse cálculo? você pensou em computá-lo em algum lugar para que seu código não precise ser misturado? Como você está alterando o código agora, talvez seja a hora de considerar isso ...).

E se você realmente quer a resposta para o porquê? Acho que você terá que pegar alguns dos desenvolvedores originais para determinar por que eles escolheram o padrão que escolheram. Mais uma vez, acho que não era um "F the standards!" escolha, mas "Quais padrões?"

Há algumas informações aqui que podem ser úteis:

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
fonte
Tecnicamente, tudo o que devo fazer é alterar minha tabela do DimCalendar, infelizmente, nossos desenvolvedores decidiram não usá-la em várias instâncias de relatório, para que ela seja calculada em tempo real. De um modo geral, isso foi mais um exercício de curiosidade do que qualquer tipo de crise.
Zane
5
Sugiro que seus desenvolvedores atualizem seus relatórios para seguir as práticas recomendadas, em vez de codificar cowboys. Mas sou só eu.
Aaron Bertrand
1
A boa notícia é que em menos de uma semana eles não serão mais meus desenvolvedores. :)
Zane
2

Existem várias autoridades assumindo condições diferentes para a primeira semana do ano. Alguns assumem que o primeiro dia da semana começa na primeira semana, mas a idéia mais comum é que a primeira semana que tem a primeira quinta-feira seja a primeira semana do ano.

Portanto, ISO_WEEKaceita isso e, como em 2010, 2011 ou 2012, como você pode verificar, ISO_WEEKdizendo que 1º de janeiro é a 52a ou 53a semana, enquanto WEEKou WKou WWdiz que são a primeira semana.

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