Last week I had a nice challenge. In the KPI table I use for certain reports, only the normal working days are calculated, Monday to Friday. Public holidays are in there too. The weekends are left out on purpose because of FTE counts, which otherwise do not work out right.

When I calculated the KPIs I ran into trouble, because the source systems entered values for certain KPIs on weekends. The question was: on which day do we put these values? My first idea was to simply put them on the Friday before. That is not always correct, because the Friday before can also fall in another month/year :-) My report runs per month, so this is not a good solution either.

For this problem I could write complicated SQL to find the right day for the value, before I loaded the data into the fact. A better solution would be to work out the correct date in advance and store it in the date table. Every date then gets a “BoekDatumID”. The definition of this field is that it must be the nearest working day that falls in the same month/year and is not a public holiday.

Now of course you want to know what the SQL looks like to find the right working day. It is fairly simple, but you have to think of it first!

werkdagen_SQL

Explanation: we explode the dates. For each date we select the 10 days before and the 10 days after that fall in the same month/year. Then we select the nearest day with RowNumber = 1.

werkdag_berekenen

Easy?!?! You use this result to update your date table. See the attachment for the SQL

Frequently asked questions

How do I find the nearest working day for a date in SQL Server?

For each date, select the 10 days before and the 10 days after that fall in the same month and year. From those, pick the nearest working day with RowNumber = 1.

Why not simply move weekend values to the Friday before?

The Friday before can fall in another month or another year. A report that runs per month then gives a wrong result.

What is a BoekDatumID in a date table?

It is a field in the date table with the nearest working day for each date. That day falls in the same month and year and is not a public holiday. That way you do not need complicated SQL up front.

Why store the correct date in the date table instead of during the load?

Complicated SQL just before loading the fact table also works. It is better to work out the correct date in advance and store it in the date table. You update the date table with the result.

Why are weekends missing from a KPI table?

The weekends are left out on purpose because of FTE counts, which otherwise do not work out right. Only Monday to Friday are in it. So values from source systems on a weekend must move to a working day.

1 comment

Your email address is not shown. A photo comes from Gravatar, if you have one.

  1. Ronald KraijesteijnAuthor

    SELECT *
    FROM
    (SELECT DD.DatumId, DD.DatumWaarde, BD.DatumID AS BoekDatumID
    ,ROW_NUMBER() OVER(PARTITION BY DD.DatumId
    ORDER BY
    (CASE WHEN DD.WeekNummer = BD.WeekNummer THEN 0 ELSE 1 END) ASC,
    ABS(DATEDIFF(dd,DD.DatumWaarde, BD.DatumWaarde)) ASC,
    BD.DagNummerVanWeek ASC
    ) AS RowID
    FROM dbo.DimDatum AS DD
    -- BD: Boek Datum
    INNER JOIN dbo.DimDatum AS BD
    ON DD.Jaar = BD.Jaar
    AND DD.MaandNummerVanJaar = BD.MaandNummerVanJaar
    WHERE ABS(DATEDIFF(dd,DD.DatumWaarde, BD.DatumWaarde))<=10
    AND (DD.IsWerkDag=0 OR DD.IsFeestDag_NL=1)
    AND BD.IsWerkDag=1
    AND BD.IsFeestDag_NL=0
    ) AS X
    WHERE X.RowID=1