In Microsoft Access, I have a table where number of hours worked per weekday are associated to a project number, ISO-week number and year. Simplified, it looks like this:
ProjectID | WeekNumber | YearNumber | Monday | Tuesday |
---|---|---|---|---|
1 | 1 | 2022 | 5 | 6 |
1 | 2 | 2022 | 7 | 8 |
I am trying to set up a query where all weekday columns (monday to sunday) are “merged” into one column and the week and year numbers are converted to dates. It should look like this:
ProjectID | Date | HoursPerDay |
---|---|---|
1 | 03.01.2022 | 5 |
1 | 04.01.2022 | 6 |
1 | 10.01.2022 | 7 |
1 | 11.01.2022 | 8 |
I managed to merge all weekday columns into one column using a UNION query:
SELECT ProjectID, WeekNumber, YearNumber, Monday As HoursPerDay FROM ProjectHours UNION ALL SELECT ProjectID, WeekNumber, YearNumber, Tuesday As HoursPerDay FROM ProjectHours;
The result looks like this:
ProjectID | WeekNumber | YearNumber | HoursPerDay |
---|---|---|---|
1 | 1 | 2022 | 5 |
1 | 1 | 2022 | 6 |
1 | 2 | 2022 | 7 |
1 | 2 | 2022 | 8 |
But I am stuck converting the iso-week and year number to a date. Is this at all possible in Access-SQL?
I found this question on Stackoverflow and went through the date/time functions that Microsoft lists for Access but could not get it to work.
Any help is highly appreciated.
EDIT: A community member has suggested a possible duplicate of this question, but I am looking for a solution that I can use in an Access-SQL query, so the suggested duplicate does not help me, as it suggests a VBA based solution.
Advertisement
Answer
This is not so simple, as the ISO years rarely are in sync with calendar years.
But this function will do:
' Returns the date of Monday for the ISO 8601 week of IsoYear and Week. ' Optionally, returns the date of any other weekday of that week. ' ' 2017-05-03. Gustav Brock, Cactus Data ApS, CPH. ' Public Function DateYearWeek( _ ByVal IsoWeek As Integer, _ Optional ByVal IsoYear As Integer, _ Optional ByVal DayOfWeek As VbDayOfWeek = VbDayOfWeek.vbMonday) _ As Date Dim WeekDate As Date Dim ResultDate As Date If IsoYear = 0 Then IsoYear = Year(Date) End If ' Validate parameters. If Not IsWeekday(DayOfWeek) Then ' Don't accept invalid values for DayOfWeek. Err.Raise DtError.dtInvalidProcedureCallOrArgument Exit Function End If If Not IsWeek(IsoWeek, IsoYear) Then ' A valid week number must be passed. Err.Raise DtError.dtInvalidProcedureCallOrArgument Exit Function End If WeekDate = DateAdd(IntervalSetting(dtWeek), IsoWeek - 1, DateFirstWeekYear(IsoYear)) ResultDate = DateThisWeekPrimo(WeekDate, DayOfWeek) DateYearWeek = ResultDate End Function
However, it uses a series of supporting functions, like:
' Returns the primo date of the week of the date passed. ' ' 2016-01-13. Gustav Brock, Cactus Data ApS, CPH. ' Public Function DateThisWeekPrimo( _ ByVal DateThisWeek As Date, _ Optional ByVal FirstDayOfWeek As VbDayOfWeek = vbSunday) _ As Date Dim Interval As String Dim Number As Double Dim ResultDate As Date Number = 0 Interval = IntervalSetting(DtInterval.dtWeek) ResultDate = DateIntervalPrimo(Interval, Number, DateThisWeek, FirstDayOfWeek) DateThisWeekPrimo = ResultDate End Function
and several more – way too much to post here.
So, please refer to my project at GitHub, VBA.Date, for the modules holding the full code.