SQL Server heeft een ingebouwde functie om het aantal weken tussen twee datums te berekenen. Deze functie heet “DateDiff”. Het probleem met deze functie is dat SQL Server denkt dat de week op zondag begint. Misschien klopt dat in sommige situaties, maar bij mijn huidige project moet de week op maandag beginnen. Hier lees je meer over hoe je het probleem met datediff en weken oplost.
Een voorbeeld:
SELECT DATEDIFF(wk,'2012-01-07', '2012-01-08')7 januari is een zaterdag, 8 januari is een zondag. Het antwoord van SQL Server is 1. Dat klopt, want de nieuwe week begint op zondag.
Oké, het probleem is duidelijk. Hoe los ik het op? Na wat zoekwerk vond ik een artikel over Visual Basic. VB heeft een vergelijkbare functie om met datums te rekenen:
DateDiff(interval, date1, date2 [,firstdayofweek[, firstweekofyear]])
Helaas bestaat dat laatste argument niet in SQL Server. Ik zocht verder op internet en vond dit.
SET LANGUAGE DutchSpecifies the language environment for the session. The session language determines the datetime formats and system messages.
Na dit SET LANGUAGE-commando draai ik het DateDiff-commando opnieuw:
SELECT DATEDIFF(wk,CAST('2012-01-07' AS DATETIME), CAST('2012-01-08' AS DATETIME) )En het antwoord? 4. Dit snap ik niet. Hoe kan dat? Ik denk dat het komt doordat de datumnotatie in het Nederlands YYYYDDMM is. SQL Server denkt dan dat ik juli tot augustus bedoel, en dan klopt het antwoord.
Als ik de maand en de dag omdraai:
SELECT DATEDIFF(wk,CAST('2012-07-01' AS DATETIME), CAST('2012-08-01' AS DATETIME) )krijg ik als antwoord: 1. Conclusie: deze functie negeert de taalinstelling en rekent altijd met zondag als eerste dag van de week.
Dit is ook interessant: als ik een integer naar datetime cast, negeert SQL Server de taalinstelling:
Er is een workaround voor dit probleem. Ik vond de functie @@DATEFIRST. Die had ik nog nooit gebruikt. Probeer dit eens:
SET LANGUAGE DutchSELECT @@DATEFIRST;
SET LANGUAGE us_englishSELECT @@DATEFIRST;Deze functie geeft een nummer terug: de eerste dag van de week. In Nederland is dat 1. Dat betekent maandag. In de VS is het 7, en dat betekent zondag. Met die kennis kan ik een mooi statement maken voor de berekening.
SET LANGUAGE Dutch;SELECT DATEDIFF( week,DATEADD(day, -@@DATEFIRST, '20091227'),DATEADD(day, -@@DATEFIRST, '20091228') );Antwoord: 1 = Correct.
De makkelijke manier: we weten dat @@DATEFIRST in mijn situatie altijd 1 teruggeeft. Dus dit werkt ook:
SELECT DATEDIFF( week,DATEADD(day, -1, '20120108'),DATEADD(day, -1, '20120109') ) AS WeekDifference;Vrijdag tot zaterdag wordt donderdag tot vrijdag: verschil = 0 weken (eerst: 0 weken) Zaterdag tot zondag wordt vrijdag tot zaterdag: verschil = 0 weken (eerst: 1 week) Zondag tot maandag wordt zaterdag tot zondag: verschil = 1 week (eerst: 0 weken)
Ik hoop dat je hiermee de DateDiff-functie goed kunt toepassen.
Veelgestelde vragen
Waarom geeft DATEDIFF met week 1 terug tussen een zaterdag en een zondag in SQL Server?
DATEDIFF gaat ervan uit dat de week op zondag begint. Van 2012-01-07 (zaterdag) naar 2012-01-08 (zondag) begint een nieuwe week, dus het antwoord is 1, al is er maar één dag voorbij.
Hoe laat ik DATEDIFF weken tellen die op maandag beginnen?
Trek voor de aanroep van beide datums één dag af: DATEDIFF(week, DATEADD(day, -1, date1), DATEADD(day, -1, date2)). Dit werkt als @@DATEFIRST 1 is, zoals in Nederland.
Verandert SET LANGUAGE hoe DATEDIFF weken telt?
Nee. Na SET LANGUAGE Dutch ziet DATEDIFF met het interval wk zondag nog steeds als de eerste dag van de week. De functie negeert de taalinstelling.
Wat geeft @@DATEFIRST terug in SQL Server?
Het nummer van de eerste dag van de week. Na SET LANGUAGE Dutch is dat 1, dus maandag. Na SET LANGUAGE us_english is het 7, dus zondag.
Kan ik de eerste dag van de week instellen in de functie DATEDIFF?
Nee. Visual Basic heeft in zijn DateDiff een argument firstdayofweek, maar SQL Server niet. Gebruik de workaround met @@DATEFIRST of schuif beide datums één dag op.


1 reactie
I think there is an easier solution for this...you can set the first day of the week:
http://msdn.microsoft.com/en-us/library/ms181598.aspx
Gerelateerde blogs
Script om het aantal rijen in alle tabellen te tellen
Ident-kolom resetten in een database
DateDiff berekenen met alleen weekdagen of werkdagen