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:

SQL
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.

datediff_wk

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.

SQL
SET LANGUAGE Dutch

Specifies 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:

SQL
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:

SQL
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:

datadiff_2

Er is een workaround voor dit probleem. Ik vond de functie @@DATEFIRST. Die had ik nog nooit gebruikt. Probeer dit eens:

SQL
SET LANGUAGE Dutch
SELECT @@DATEFIRST;
SET LANGUAGE us_english
SELECT @@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.

SQL
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:

SQL
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

Je e-mailadres wordt niet getoond. Een foto komt van Gravatar, als je die hebt.

  1. Rogier Pronk

    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