Repository: dhsc-govuk/FingertipsNext
Pull request #566: Add PeriodDimension and DateDimension tables and populate them
Author: login: andyevans-bjss
Created: 2025-05-09T14:52:03Z | Merged: 2025-05-15T11:34:50Z

# Description

Jira ticket: [DHSCFT-749](https://bjss-enterprise.atlassian.net/browse/DHSCFT-749)

As part of the work to support time periods other than simple years this PR adds support at the database schema level. 

## Changes

- Create a DateDimension table to store all relevant days along with useful info about each date.
- Populate the DateDimension table with all days from 1st December 2000 to 1st December 2035
- Create a PeriodDimension table to hold period types
- Populate the PeriodDimension table with known periods like calendar year, quarter etc. 
- Add a FromDateKey and ToDateKey columns to the HealthMeasure table that are keyed to the DateDimension table. Initially these are nullable.
- Add a PeriodKey to the HealthMeasure table keyed to the PeriodDimension table.
- Update the PopulateFingertips.sql script to populate the 2 new tables
- Etc.

## Validation

Build the db container locally, check if the deployed database matches expectations nd has the expected data



Diff:
diff --git a/database/fingertips-db/PostDeployment/PopulateFingertips.sql b/database/fingertips-db/PostDeployment/PopulateFingertips.sql
index 22fcd8417..95ca23f5b 100644
--- a/database/fingertips-db/PostDeployment/PopulateFingertips.sql
+++ b/database/fingertips-db/PostDeployment/PopulateFingertips.sql
@@ -48,6 +48,20 @@ BEGIN CATCH
 END CATCH;
 GO
 
+BEGIN TRY 
+    DELETE FROM [dbo].[DateDimension];
+END TRY
+BEGIN CATCH
+END CATCH;
+GO
+
+BEGIN TRY 
+    DELETE FROM [dbo].[PeriodDimension];
+END TRY
+BEGIN CATCH
+END CATCH;
+GO
+
 BEGIN TRY 
     DELETE FROM [Areas].[AreaRelationships];
 END TRY
@@ -70,6 +84,8 @@ END CATCH;
 GO
 
 
+
+
 --reseed the tables, starting from 0. Currently identity insert is turned off for this seeding data
 DBCC CHECKIDENT ('[HealthMeasure]', RESEED, 0);
 DBCC CHECKIDENT ('[AgeDimension]', RESEED, 0);
@@ -78,7 +94,10 @@ DBCC CHECKIDENT ('[DeprivationDimension]', RESEED, 0);
 DBCC CHECKIDENT ('[IndicatorDimension]', RESEED, 0);
 DBCC CHECKIDENT ('[SexDimension]', RESEED, 0);
 DBCC CHECKIDENT ('[TrendDimension]', RESEED, 0);
+DBCC CHECKIDENT ('[DateDimension]', RESEED, 0);
+DBCC CHECKIDENT ('[PeriodDimension]', RESEED, 0);
 DBCC CHECKIDENT ('[Areas].[Areas]', RESEED, 0);
+
 --create some sex dimension data
 INSERT INTO [dbo].[SexDimension] 
 	(
@@ -91,6 +110,20 @@ INSERT INTO [dbo].[SexDimension]
 	('Female',1,2),
 	('Persons',0,4)
 
+--create some period data
+INSERT INTO [dbo].[PeriodDimension]
+(Period)
+VALUES
+('Year'),
+('Quarter'),
+('Month'),
+('Week'),
+('Day'),
+('Financial Year'),
+('Academic Year'),
+('2 Year'),
+('3 Year'),
+('5 Year')
 
 --create the trend dimension data
 SET IDENTITY_INSERT [dbo].[TrendDimension] ON
@@ -106,6 +139,75 @@ INSERT [dbo].[TrendDimension] ([TrendKey], [Name], [HasValue]) VALUES (9, N'Decr
 SET IDENTITY_INSERT [dbo].[TrendDimension] OFF
 GO
 
+--populate the DateDimension table
+DECLARE @CurrentDate DATE = '2000-01-01'
+DECLARE @EndDate DATE = '2035-12-31'
+
+WHILE @CurrentDate < @EndDate
+BEGIN
+   INSERT INTO [dbo].[DateDimension] (
+      [Date],
+      [Day],
+      [DaySuffix],
+      [Weekday],
+      [WeekDayName],
+      [DayOfYear],
+      [WeekOfMonth],
+      [WeekOfYear],
+      [Month],
+      [MonthName],
+      [MonthNameShort],
+      [Quarter],
+      [QuarterName],
+      [Year],
+      [IsWeekend]
+      )
+   SELECT 
+      DATE = @CurrentDate,
+      Day = DAY(@CurrentDate),
+      [DaySuffix] = CASE 
+         WHEN DAY(@CurrentDate) = 1
+            OR DAY(@CurrentDate) = 21
+            OR DAY(@CurrentDate) = 31
+            THEN 'st'
+         WHEN DAY(@CurrentDate) = 2
+            OR DAY(@CurrentDate) = 22
+            THEN 'nd'
+         WHEN DAY(@CurrentDate) = 3
+            OR DAY(@CurrentDate) = 23
+            THEN 'rd'
+         ELSE 'th'
+         END,
+      WEEKDAY = DATEPART(dw, @CurrentDate),
+      WeekDayName = DATENAME(dw, @CurrentDate),
+      [DayOfYear] = DATENAME(dy, @CurrentDate),
+      [WeekOfMonth] = DATEPART(WEEK, @CurrentDate) - DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM, 0, @CurrentDate), 0)) + 1,
+      [WeekOfYear] = DATEPART(wk, @CurrentDate),
+      [Month] = MONTH(@CurrentDate),
+      [MonthName] = DATENAME(mm, @CurrentDate),
+      [MonthNameShort] = UPPER(LEFT(DATENAME(mm, @CurrentDate), 3)),
+      [Quarter] = DATEPART(q, @CurrentDate),
+      [QuarterName] = CASE 
+         WHEN DATENAME(qq, @CurrentDate) = 1
+            THEN 'first'
+         WHEN DATENAME(qq, @CurrentDate) = 2
+            THEN 'second'
+         WHEN DATENAME(qq, @CurrentDate) = 3
+            THEN 'third'
+         WHEN DATENAME(qq, @CurrentDate) = 4
+            THEN 'fourth'
+         END,
+      [Year] = YEAR(@CurrentDate),
+      [IsWeekend] = CASE 
+         WHEN DATENAME(dw, @CurrentDate) = 'Sunday'
+            OR DATENAME(dw, @CurrentDate) = 'Saturday'
+            THEN 1
+         ELSE 0
+         END
+
+   SET @CurrentDate = DATEADD(DD, 1, @CurrentDate)
+END
+
 BEGIN TRY DROP TABLE #TempDeprivationData; END TRY BEGIN CATCH END CATCH;
 GO
 BEGIN TRY DROP TABLE #TempAgeData; END TRY BEGIN CATCH END CATCH;
diff --git a/database/fingertips-db/Tables/DateDimension.sql b/database/fingertips-db/Tables/DateDimension.sql
new file mode 100644
index 000000000..b0e44e5eb
--- /dev/null
+++ b/database/fingertips-db/Tables/DateDimension.sql
@@ -0,0 +1,25 @@
+
+CREATE TABLE [dbo].[DateDimension](
+	[DateKey] [int] IDENTITY(1,1) NOT NULL,
+	[Date] [date] NOT NULL,
+	[Day] [tinyint] NOT NULL,
+	[DaySuffix] [char](2) NOT NULL,
+	[Weekday] [tinyint] NOT NULL,
+	[WeekDayName] [varchar](10) NOT NULL,
+	[DayOfYear] [smallint] NOT NULL,
+	[WeekOfMonth] [tinyint] NOT NULL,
+	[WeekOfYear] [tinyint] NOT NULL,
+	[Month] [tinyint] NOT NULL,
+	[MonthName] [varchar](10) NOT NULL,
+	[MonthNameShort] [char](3) NOT NULL,
+	[Quarter] [tinyint] NOT NULL,
+	[QuarterName] [varchar](6) NOT NULL,
+	[Year] [int] NOT NULL,
+	[IsWeekend] [bit] NOT NULL,
+ CONSTRAINT [PK__DateDimension] PRIMARY KEY CLUSTERED 
+(
+	[DateKey] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
+) ON [PRIMARY]
+GO
+
diff --git a/database/fingertips-db/Tables/HealthMeasure.sql b/database/fingertips-db/Tables/HealthMeasure.sql
index 61b352a67..217ef6c7a 100644
--- a/database/fingertips-db/Tables/HealthMeasure.sql
+++ b/database/fingertips-db/Tables/HealthMeasure.sql
@@ -12,10 +12,13 @@ CREATE TABLE [dbo].[HealthMeasure](
 	[Value] [float] NULL,                             --The value of the data e.g. how many people per 100 000. This is the key piece of data for this row
 	[LowerCI] [float] NULL,                           --The lower confidence interval value - a statistically calculated value using methodology described in the indicator metadata
 	[UpperCI] [float] NULL,                           --The upper confidence interval value - a statistically calculated value using methodology described in the indicator metadata
-	[Year] [smallint] NOT NULL,                       --A junk dimension of the year that this row is for e.g. 2022
+	[Year] [smallint] NOT NULL,                       --A junk dimension of the year that this row is for e.g. 2022, will be deprecated
 	[IsSexAggregatedOrSingle] bit NULL,
 	[IsAgeAggregatedOrSingle] bit NULL,
-	[IsDeprivationAggregatedOrSingle] bit NULL
+	[IsDeprivationAggregatedOrSingle] bit NULL,
+	[FromDateKey] [int] NULL,
+	[ToDateKey] [int] NULL,
+	[PeriodKey] [tinyint] NULL
  CONSTRAINT [PK_HealthMeasure] PRIMARY KEY CLUSTERED
 (
 	[HealthMeasureKey] ASC
@@ -60,6 +63,27 @@ GO
 ALTER TABLE [dbo].[HealthMeasure] CHECK CONSTRAINT [FK_HealthMeasure_DeprivationDimension]
 GO
 
+ALTER TABLE [dbo].[HealthMeasure]  WITH CHECK ADD  CONSTRAINT [FK_HealthMeasure_FromDateDimension] FOREIGN KEY([FromDateKey])
+REFERENCES [dbo].[DateDimension] ([DateKey])
+GO
+
+ALTER TABLE [dbo].[HealthMeasure] CHECK CONSTRAINT [FK_HealthMeasure_FromDateDimension]
+GO
+
+ALTER TABLE [dbo].[HealthMeasure]  WITH CHECK ADD  CONSTRAINT [FK_HealthMeasure_ToDateDimension] FOREIGN KEY([ToDateKey])
+REFERENCES [dbo].[DateDimension] ([DateKey])
+GO
+
+ALTER TABLE [dbo].[HealthMeasure] CHECK CONSTRAINT [FK_HealthMeasure_ToDateDimension]
+GO
+
+ALTER TABLE [dbo].[HealthMeasure]  WITH CHECK ADD  CONSTRAINT [FK_HealthMeasure_PeriodDimension] FOREIGN KEY([PeriodKey])
+REFERENCES [dbo].[PeriodDimension] ([PeriodKey])
+GO
+
+ALTER TABLE [dbo].[HealthMeasure] CHECK CONSTRAINT [FK_HealthMeasure_PeriodDimension]
+GO
+
 CREATE NONCLUSTERED INDEX [AgeIndex] ON [dbo].[HealthMeasure]
 (
 	[AgeKey] ASC
@@ -102,6 +126,24 @@ CREATE NONCLUSTERED INDEX [YearIndex] ON [dbo].[HealthMeasure]
 )
 GO
 
+CREATE NONCLUSTERED INDEX [FromDateIndex] ON [dbo].[HealthMeasure]
+(
+	[FromDateKey] ASC
+)
+GO
+
+CREATE NONCLUSTERED INDEX [ToDateIndex] ON [dbo].[HealthMeasure]
+(
+	[ToDateKey] ASC
+)
+GO
+
+CREATE NONCLUSTERED INDEX [PeriodIndex] ON [dbo].[HealthMeasure]
+(
+	[PeriodKey] ASC
+)
+GO
+
 CREATE NONCLUSTERED INDEX InequalitiesAggregatedIndex
 ON [dbo].[HealthMeasure] ([IsSexAggregatedOrSingle],[IsAgeAggregatedOrSingle],[IsDeprivationAggregatedOrSingle])
 INCLUDE ([AgeKey],[AreaKey],[IndicatorKey],[SexKey],[TrendKey],[DeprivationKey],[Count],[Value],[LowerCI],[UpperCI],[Year])
diff --git a/database/fingertips-db/Tables/PeriodDimension.sql b/database/fingertips-db/Tables/PeriodDimension.sql
new file mode 100644
index 000000000..fc542a49b
--- /dev/null
+++ b/database/fingertips-db/Tables/PeriodDimension.sql
@@ -0,0 +1,10 @@
+CREATE TABLE [dbo].[PeriodDimension](
+	[PeriodKey] [tinyint] IDENTITY(1,1) NOT NULL,
+	[Period] [nvarchar](50) NOT NULL,
+ CONSTRAINT [PK_PeriodDimension] PRIMARY KEY CLUSTERED 
+(
+	[PeriodKey] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
+) ON [PRIMARY]
+GO
+
diff --git a/database/fingertips-db/fingertips-db.sqlproj b/database/fingertips-db/fingertips-db.sqlproj
index 3a938bc17..f88ec7845 100644
--- a/database/fingertips-db/fingertips-db.sqlproj
+++ b/database/fingertips-db/fingertips-db.sqlproj
@@ -26,6 +26,8 @@
     <Build Include="Tables\IndicatorDimension.sql" />
     <Build Include="Tables\SexDimension.sql" />
     <Build Include="Tables\TrendDimension.sql" />
+    <Build Include="Tables\DateDimension.sql" />
+    <Build Include="Tables\PeriodDimension.sql" />
     <Build Include="Security\Areas.sql" />
     <Build Include="Tables\Areas.sql" />
     <Build Include="Tables\AreaRelationships.sql" />


Reviews:
user: login: stuc-bjss
body: Looks good to me
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T15:44:00Z
user: login: HowardMayCGI
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:19:29Z
user: login: HowardMayCGI
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:20:53Z
user: login: HowardMayCGI
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:24:24Z
user: login: HowardMayCGI
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:27:19Z
user: login: gareth-allan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T13:39:51Z
user: login: gareth-allan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T13:45:17Z
user: login: andyevans-bjss
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T09:25:24Z
user: login: andyevans-bjss
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T09:27:39Z
user: login: andyevans-bjss
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T09:28:46Z
user: login: andyevans-bjss
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T09:29:08Z
user: login: gareth-allan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T09:59:33Z

Review comments:
diff_hunk: @@ -0,0 +1,25 @@
+
+CREATE TABLE [dbo].[DateDimension](
+	[DateKey] [int] IDENTITY(1,1) NOT NULL,
+	[Date] [date] NOT NULL,
+	[Day] [tinyint] NOT NULL,
+	[DaySuffix] [char](2) NOT NULL,
+	[Weekday] [tinyint] NOT NULL,
+	[WeekDayName] [varchar](10) NOT NULL,
+	[DayOfYear] [smallint] NOT NULL,
+	[WeekOfMonth] [tinyint] NOT NULL,
+	[WeekOfYear] [tinyint] NOT NULL,
+	[Month] [tinyint] NOT NULL,
+	[MonthName] [varchar](10) NOT NULL,
+	[MonthNameShort] [char](3) NOT NULL,
+	[Quarter] [tinyint] NOT NULL,
+	[QuarterName] [varchar](6) NOT NULL,
+	[Year] [int] NOT NULL,
+	[IsWeekend] [bit] NOT NULL,
+ CONSTRAINT [PK__DateDimension] PRIMARY KEY CLUSTERED 
+(
+	[DateKey] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
path: database/fingertips-db/Tables/DateDimension.sql
user: login: HowardMayCGI
body: Have you changed any of these options from default values and if so ... why?
created_at: 2025-05-12T08:19:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,7 +15,10 @@ CREATE TABLE [dbo].[HealthMeasure](
 	[Year] [smallint] NOT NULL,                       --A junk dimension of the year that this row is for e.g. 2022
path: database/fingertips-db/Tables/HealthMeasure.sql
user: login: HowardMayCGI
body: I think it's worth updatting the commen for the year to make it clear that this is now a deprecated field which will be being removed. 
created_at: 2025-05-12T08:20:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -102,6 +126,24 @@ CREATE NONCLUSTERED INDEX [YearIndex] ON [dbo].[HealthMeasure]
 )
 GO
 
+CREATE NONCLUSTERED INDEX [FromDateIndex] ON [dbo].[HealthMeasure]
+(
+	[FromDateKey] ASC
+)
+GO
+
+CREATE NONCLUSTERED INDEX [ToDateIndex] ON [dbo].[HealthMeasure]
+(
+	[ToDateKey] ASC
+)
+GO
+
+CREATE NONCLUSTERED INDEX [PeriodIndex] ON [dbo].[HealthMeasure]
path: database/fingertips-db/Tables/HealthMeasure.sql
user: login: HowardMayCGI
body: The Primark Key in the Date table it CLUSTETED but these index's are nonclustered. I don't know enough to say that that is wrong but it seems like a miss-match
created_at: 2025-05-12T08:24:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,6 +139,75 @@ INSERT [dbo].[TrendDimension] ([TrendKey], [Name], [HasValue]) VALUES (9, N'Decr
 SET IDENTITY_INSERT [dbo].[TrendDimension] OFF
 GO
 
+--populate the DateDimension table
+DECLARE @CurrentDate DATE = '2000-01-01'
+DECLARE @EndDate DATE = '2035-12-31'
path: database/fingertips-db/PostDeployment/PopulateFingertips.sql
user: login: HowardMayCGI
body: This is only 10 years in the future - it's sufficiently close that we have to consider it - is there any harm making it 20 years?
created_at: 2025-05-12T08:27:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,6 +139,75 @@ INSERT [dbo].[TrendDimension] ([TrendKey], [Name], [HasValue]) VALUES (9, N'Decr
 SET IDENTITY_INSERT [dbo].[TrendDimension] OFF
 GO
 
+--populate the DateDimension table
+DECLARE @CurrentDate DATE = '2000-01-01'
+DECLARE @EndDate DATE = '2035-12-31'
+
+WHILE @CurrentDate < @EndDate
+BEGIN
+   INSERT INTO [dbo].[DateDimension] (
+      [Date],
+      [Day],
+      [DaySuffix],
+      [Weekday],
+      [WeekDayName],
+      [DayOfYear],
+      [WeekOfMonth],
+      [WeekOfYear],
+      [Month],
+      [MonthName],
+      [MonthNameShort],
+      [Quarter],
+      [QuarterName],
+      [Year],
+      [IsWeekend]
+      )
+   SELECT 
+      DATE = @CurrentDate,
+      Day = DAY(@CurrentDate),
+      [DaySuffix] = CASE 
+         WHEN DAY(@CurrentDate) = 1
+            OR DAY(@CurrentDate) = 21
+            OR DAY(@CurrentDate) = 31
+            THEN 'st'
+         WHEN DAY(@CurrentDate) = 2
+            OR DAY(@CurrentDate) = 22
+            THEN 'nd'
+         WHEN DAY(@CurrentDate) = 3
+            OR DAY(@CurrentDate) = 23
+            THEN 'rd'
+         ELSE 'th'
+         END,
+      WEEKDAY = DATEPART(dw, @CurrentDate),
+      WeekDayName = DATENAME(dw, @CurrentDate),
+      [DayOfYear] = DATENAME(dy, @CurrentDate),
+      [WeekOfMonth] = DATEPART(WEEK, @CurrentDate) - DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM, 0, @CurrentDate), 0)) + 1,
+      [WeekOfYear] = DATEPART(wk, @CurrentDate),
+      [Month] = MONTH(@CurrentDate),
+      [MonthName] = DATENAME(mm, @CurrentDate),
+      [MonthNameShort] = UPPER(LEFT(DATENAME(mm, @CurrentDate), 3)),
+      [Quarter] = DATEPART(q, @CurrentDate),
+      [QuarterName] = CASE 
+         WHEN DATENAME(qq, @CurrentDate) = 1
+            THEN 'First'
+         WHEN DATENAME(qq, @CurrentDate) = 2
+            THEN 'second'
+         WHEN DATENAME(qq, @CurrentDate) = 3
+            THEN 'third'
+         WHEN DATENAME(qq, @CurrentDate) = 4
+            THEN 'fourth'
path: database/fingertips-db/PostDeployment/PopulateFingertips.sql
user: login: gareth-allan
body: You've got `First` capitalised here but none of the rest of the quarter names are.
created_at: 2025-05-12T13:39:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,6 +139,75 @@ INSERT [dbo].[TrendDimension] ([TrendKey], [Name], [HasValue]) VALUES (9, N'Decr
 SET IDENTITY_INSERT [dbo].[TrendDimension] OFF
 GO
 
+--populate the DateDimension table
+DECLARE @CurrentDate DATE = '2000-01-01'
+DECLARE @EndDate DATE = '2035-12-31'
+
+WHILE @CurrentDate < @EndDate
+BEGIN
+   INSERT INTO [dbo].[DateDimension] (
+      [Date],
+      [Day],
+      [DaySuffix],
+      [Weekday],
+      [WeekDayName],
+      [DayOfYear],
+      [WeekOfMonth],
+      [WeekOfYear],
+      [Month],
+      [MonthName],
+      [MonthNameShort],
+      [Quarter],
+      [QuarterName],
+      [Year],
+      [IsWeekend]
+      )
+   SELECT 
+      DATE = @CurrentDate,
+      Day = DAY(@CurrentDate),
+      [DaySuffix] = CASE 
+         WHEN DAY(@CurrentDate) = 1
+            OR DAY(@CurrentDate) = 21
+            OR DAY(@CurrentDate) = 31
+            THEN 'st'
+         WHEN DAY(@CurrentDate) = 2
+            OR DAY(@CurrentDate) = 22
+            THEN 'nd'
+         WHEN DAY(@CurrentDate) = 3
+            OR DAY(@CurrentDate) = 23
+            THEN 'rd'
+         ELSE 'th'
+         END,
+      WEEKDAY = DATEPART(dw, @CurrentDate),
path: database/fingertips-db/PostDeployment/PopulateFingertips.sql
user: login: gareth-allan
body: Looks like this is treating Sunday as the first day of the week. Not to start an argument, but is that what we want?

It's producing `Weekday`/`WeekDayName` combinations of:
- 1 `Sunday`
- 2 `Monday`
- 3 `Tuesday`
- 4 `Wednesday`
- 5 `Thursday`
- 6 `Friday`
- 7 `Saturday`
created_at: 2025-05-12T13:45:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,7 +15,10 @@ CREATE TABLE [dbo].[HealthMeasure](
 	[Year] [smallint] NOT NULL,                       --A junk dimension of the year that this row is for e.g. 2022
path: database/fingertips-db/Tables/HealthMeasure.sql
user: login: andyevans-bjss
body: default options
created_at: 2025-05-13T09:25:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -102,6 +126,24 @@ CREATE NONCLUSTERED INDEX [YearIndex] ON [dbo].[HealthMeasure]
 )
 GO
 
+CREATE NONCLUSTERED INDEX [FromDateIndex] ON [dbo].[HealthMeasure]
+(
+	[FromDateKey] ASC
+)
+GO
+
+CREATE NONCLUSTERED INDEX [ToDateIndex] ON [dbo].[HealthMeasure]
+(
+	[ToDateKey] ASC
+)
+GO
+
+CREATE NONCLUSTERED INDEX [PeriodIndex] ON [dbo].[HealthMeasure]
path: database/fingertips-db/Tables/HealthMeasure.sql
user: login: andyevans-bjss
body: Yes, PK is clustered and there can only be one clustered index for each table
created_at: 2025-05-13T09:27:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,6 +139,75 @@ INSERT [dbo].[TrendDimension] ([TrendKey], [Name], [HasValue]) VALUES (9, N'Decr
 SET IDENTITY_INSERT [dbo].[TrendDimension] OFF
 GO
 
+--populate the DateDimension table
+DECLARE @CurrentDate DATE = '2000-01-01'
+DECLARE @EndDate DATE = '2035-12-31'
+
+WHILE @CurrentDate < @EndDate
+BEGIN
+   INSERT INTO [dbo].[DateDimension] (
+      [Date],
+      [Day],
+      [DaySuffix],
+      [Weekday],
+      [WeekDayName],
+      [DayOfYear],
+      [WeekOfMonth],
+      [WeekOfYear],
+      [Month],
+      [MonthName],
+      [MonthNameShort],
+      [Quarter],
+      [QuarterName],
+      [Year],
+      [IsWeekend]
+      )
+   SELECT 
+      DATE = @CurrentDate,
+      Day = DAY(@CurrentDate),
+      [DaySuffix] = CASE 
+         WHEN DAY(@CurrentDate) = 1
+            OR DAY(@CurrentDate) = 21
+            OR DAY(@CurrentDate) = 31
+            THEN 'st'
+         WHEN DAY(@CurrentDate) = 2
+            OR DAY(@CurrentDate) = 22
+            THEN 'nd'
+         WHEN DAY(@CurrentDate) = 3
+            OR DAY(@CurrentDate) = 23
+            THEN 'rd'
+         ELSE 'th'
+         END,
+      WEEKDAY = DATEPART(dw, @CurrentDate),
+      WeekDayName = DATENAME(dw, @CurrentDate),
+      [DayOfYear] = DATENAME(dy, @CurrentDate),
+      [WeekOfMonth] = DATEPART(WEEK, @CurrentDate) - DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM, 0, @CurrentDate), 0)) + 1,
+      [WeekOfYear] = DATEPART(wk, @CurrentDate),
+      [Month] = MONTH(@CurrentDate),
+      [MonthName] = DATENAME(mm, @CurrentDate),
+      [MonthNameShort] = UPPER(LEFT(DATENAME(mm, @CurrentDate), 3)),
+      [Quarter] = DATEPART(q, @CurrentDate),
+      [QuarterName] = CASE 
+         WHEN DATENAME(qq, @CurrentDate) = 1
+            THEN 'First'
+         WHEN DATENAME(qq, @CurrentDate) = 2
+            THEN 'second'
+         WHEN DATENAME(qq, @CurrentDate) = 3
+            THEN 'third'
+         WHEN DATENAME(qq, @CurrentDate) = 4
+            THEN 'fourth'
path: database/fingertips-db/PostDeployment/PopulateFingertips.sql
user: login: andyevans-bjss
body: changed
created_at: 2025-05-13T09:28:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,6 +139,75 @@ INSERT [dbo].[TrendDimension] ([TrendKey], [Name], [HasValue]) VALUES (9, N'Decr
 SET IDENTITY_INSERT [dbo].[TrendDimension] OFF
 GO
 
+--populate the DateDimension table
+DECLARE @CurrentDate DATE = '2000-01-01'
+DECLARE @EndDate DATE = '2035-12-31'
+
+WHILE @CurrentDate < @EndDate
+BEGIN
+   INSERT INTO [dbo].[DateDimension] (
+      [Date],
+      [Day],
+      [DaySuffix],
+      [Weekday],
+      [WeekDayName],
+      [DayOfYear],
+      [WeekOfMonth],
+      [WeekOfYear],
+      [Month],
+      [MonthName],
+      [MonthNameShort],
+      [Quarter],
+      [QuarterName],
+      [Year],
+      [IsWeekend]
+      )
+   SELECT 
+      DATE = @CurrentDate,
+      Day = DAY(@CurrentDate),
+      [DaySuffix] = CASE 
+         WHEN DAY(@CurrentDate) = 1
+            OR DAY(@CurrentDate) = 21
+            OR DAY(@CurrentDate) = 31
+            THEN 'st'
+         WHEN DAY(@CurrentDate) = 2
+            OR DAY(@CurrentDate) = 22
+            THEN 'nd'
+         WHEN DAY(@CurrentDate) = 3
+            OR DAY(@CurrentDate) = 23
+            THEN 'rd'
+         ELSE 'th'
+         END,
+      WEEKDAY = DATEPART(dw, @CurrentDate),
path: database/fingertips-db/PostDeployment/PopulateFingertips.sql
user: login: andyevans-bjss
body: At this stage I don't think it matters too much
created_at: 2025-05-13T09:29:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,6 +139,75 @@ INSERT [dbo].[TrendDimension] ([TrendKey], [Name], [HasValue]) VALUES (9, N'Decr
 SET IDENTITY_INSERT [dbo].[TrendDimension] OFF
 GO
 
+--populate the DateDimension table
+DECLARE @CurrentDate DATE = '2000-01-01'
+DECLARE @EndDate DATE = '2035-12-31'
+
+WHILE @CurrentDate < @EndDate
+BEGIN
+   INSERT INTO [dbo].[DateDimension] (
+      [Date],
+      [Day],
+      [DaySuffix],
+      [Weekday],
+      [WeekDayName],
+      [DayOfYear],
+      [WeekOfMonth],
+      [WeekOfYear],
+      [Month],
+      [MonthName],
+      [MonthNameShort],
+      [Quarter],
+      [QuarterName],
+      [Year],
+      [IsWeekend]
+      )
+   SELECT 
+      DATE = @CurrentDate,
+      Day = DAY(@CurrentDate),
+      [DaySuffix] = CASE 
+         WHEN DAY(@CurrentDate) = 1
+            OR DAY(@CurrentDate) = 21
+            OR DAY(@CurrentDate) = 31
+            THEN 'st'
+         WHEN DAY(@CurrentDate) = 2
+            OR DAY(@CurrentDate) = 22
+            THEN 'nd'
+         WHEN DAY(@CurrentDate) = 3
+            OR DAY(@CurrentDate) = 23
+            THEN 'rd'
+         ELSE 'th'
+         END,
+      WEEKDAY = DATEPART(dw, @CurrentDate),
path: database/fingertips-db/PostDeployment/PopulateFingertips.sql
user: login: gareth-allan
body: Fair enough. We're not necessarily doing anything with these values straight away anyway, are we?
created_at: 2025-05-13T09:59:33Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-05-14T13:04:43Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=dhsc-govuk_FingertipsNext&pullRequest=566) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=dhsc-govuk_FingertipsNext&pullRequest=566&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=dhsc-govuk_FingertipsNext&pullRequest=566&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=dhsc-govuk_FingertipsNext&pullRequest=566&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=dhsc-govuk_FingertipsNext&pullRequest=566&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=dhsc-govuk_FingertipsNext&pullRequest=566&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=dhsc-govuk_FingertipsNext&pullRequest=566)


author_association: NONE