PostgreSQL: Generate Date Dimension
Notes
-
Holiday flag: You can update it afterward by joining with a holiday list table:
-
Fiscal year: The above example assumes fiscal years start in April. You can tweak that for your organization’s fiscal calendar.
-
Size: This script will insert ~2.9 million rows for 1900–9999. If you want a smaller table, just adjust the range in
generate_series.
MySQL 8+ : Generate Date Dimension
Important Notes
-
Performance warning:
Generating ~2.9 million rows for 1900–9999 in a recursive CTE can take a while in MySQL. If you only need, say, 1900–2100 (~73k rows), change: -
DAYOFWEEK()difference:
MySQL returns Sunday=1 … Saturday=7, unlike ISO Monday=1. If you want Monday=1, you can use: -
Holiday flag: Populate later by joining with your holiday list.
-
Fiscal year: Adjust start month in the CASE logic to match your business rules.
Here’s the optimized MySQL date dimension generator that:
-
Generates only from 1900-01-01 to 2100-12-31 (≈73,000 rows)
-
Adds a special sentinel row for
9999-12-31for SCD2 “active until infinity” handling.
MySQL: Date Dimension (1900–2100 + 9999 Sentinel)
Why this is optimal for SCD2
-
Keeps the table small (~73k rows instead of millions)
-
Supports all realistic reporting dates
-
Has a special 9999-12-31 row for “active” SCD2 records
-
Joins are fast because
date_keyis anINT -
Can still add fiscal calendars, holiday flags, etc.
Here’s a complete example of an SCD2 dimension table that uses the date_dim we just built. It shows how to store start_date_key and end_date_key pointing to date_dim, and how to query the “current” record.
1. Create the SCD2 dimension table
2. Insert example historical and current records
3. Query current/active records
4. Notes / Best Practices
-
start_date_keyandend_date_keyare FKs pointing todate_dim.-
This ensures consistency for joins and allows access to fiscal/calendar attributes.
-
-
9999-12-31sentinel indicates active/current record. -
is_currentflag is optional but convenient for fast queries. -
Updating SCD2 records:
-
When a customer changes, set the previous record’s
end_date_keytoDATE_KEY_OF_DAY_BEFORE_NEW_STARTandis_current = 'N'. -
Insert a new record with
start_date_key = new_start_dateandend_date_key = 99991231,is_current = 'Y'.
-
This pattern allows easy historical tracking, accurate reporting for any date, and works seamlessly with the date_dim you generated.

浙公网安备 33010602011771号