diff --git a/models/marts/dim_date.sql b/models/marts/dim_date.sql new file mode 100644 index 0000000..4caeaa3 --- /dev/null +++ b/models/marts/dim_date.sql @@ -0,0 +1,66 @@ +{{ + config( + materialized = "table" + ) +}} + +## What dates to start and end from, can be adjusted easily ## + +with parameters as ( + + select + date('{{ var("dim_date_start", "2023-01-01") }}') as start_date, + date('{{ var("dim_date_end", "2050-12-31") }}') as end_date + +), + +## One row per day ## + +date_spine as ( + + select + date_day + from parameters, + unnest(generate_date_array(start_date, end_date)) as date_day + +) + +select + -- date key + cast(format_date('%Y%m%d', date_day) as int64) as date_key, + + -- day information + date_day, + extract(dayofweek from date_day) as day_of_week, + format_date('%A', date_day) as day_of_week_name, + case + when extract(dayofweek from date_day) in (1, 7) then true + else false + end as is_weekend, + extract(day from date_day) as day_of_month, + extract(dayofyear from date_day) as day_of_year, + + -- week (ISO) information + extract(isoyear from date_day) as iso_year, + extract(isoweek from date_day) as iso_week_of_year, + date_trunc(date_day, week(monday)) as week_start_date, + date_add(date_trunc(date_day, week(monday)), interval 6 day) as week_end_date, + + -- month information + format_date('%B', date_day) as month_name, + extract(month from date_day) as month_of_year, + date_trunc(date_day, month) as month_start_date, + date_sub(date_add(date_trunc(date_day, month), interval 1 month), interval 1 day) as month_end_date, + + -- quarter information + extract(quarter from date_day) as quarter_of_year, + date_trunc(date_day, quarter) as quarter_start_date, + date_sub(date_add(date_trunc(date_day, quarter), interval 3 month), interval 1 day) as quarter_end_date, + + -- year (calendar) information + extract(year from date_day) as year_number, + date_trunc(date_day, year) as year_start_date, + date_sub(date_add(date_trunc(date_day, year), interval 1 year), interval 1 day) as year_end_date + +from date_spine +order by date_day diff --git a/models/marts/dim_date.yml b/models/marts/dim_date.yml new file mode 100644 index 0000000..a30848e --- /dev/null +++ b/models/marts/dim_date.yml @@ -0,0 +1,129 @@ +version: 2 + +models: + - name: dim_date + description: Date dimension table with one row per day and useful calendar attributes. + + columns: + - name: date_key + description: Integer date key in YYYYMMDD format. + tests: + - not_null + - unique + + - name: date_day + description: The calendar date. + tests: + - not_null + - unique + + - name: day_of_week + description: Day of week number where 1 = Sunday and 7 = Saturday. + tests: + - not_null + - accepted_values: + values: [1, 2, 3, 4, 5, 6, 7] + quote: false + + - name: day_of_week_name + description: Name of the day of the week. + tests: + - not_null + - accepted_values: + values: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] + + - name: is_weekend + description: True when the date falls on Saturday or Sunday. + tests: + - not_null + - accepted_values: + values: [true, false] + quote: false + + - name: day_of_month + description: Day number within the month. + tests: + - not_null + + - name: day_of_year + description: Day number within the year. + tests: + - not_null + + - name: iso_year + description: ISO week-numbering year. + tests: + - not_null + + - name: iso_week_of_year + description: ISO week number within the ISO year. + tests: + - not_null + + - name: week_start_date + description: Start date of the ISO week, beginning on Monday. + tests: + - not_null + + - name: week_end_date + description: End date of the ISO week, ending on Sunday. + tests: + - not_null + + - name: month_name + description: Name of the month. + tests: + - not_null + - accepted_values: + values: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] + + - name: month_of_year + description: Month number within the year. + tests: + - not_null + - accepted_values: + values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] + quote: false + + - name: month_start_date + description: First date of the month. + tests: + - not_null + + - name: month_end_date + description: Last date of the month. + tests: + - not_null + + - name: quarter_of_year + description: Quarter number within the year. + tests: + - not_null + - accepted_values: + values: [1, 2, 3, 4] + quote: false + + - name: quarter_start_date + description: First date of the quarter. + tests: + - not_null + + - name: quarter_end_date + description: Last date of the quarter. + tests: + - not_null + + - name: year_number + description: Calendar year. + tests: + - not_null + + - name: year_start_date + description: First date of the year. + tests: + - not_null + + - name: year_end_date + description: Last date of the year. + tests: + - not_null \ No newline at end of file diff --git a/tests/singular_tests/dim_date_is_weekend_logic.sql b/tests/singular_tests/dim_date_is_weekend_logic.sql new file mode 100644 index 0000000..518d35e --- /dev/null +++ b/tests/singular_tests/dim_date_is_weekend_logic.sql @@ -0,0 +1,4 @@ +select * +from {{ ref('dim_date') }} +where (day_of_week in (1, 7) and is_weekend != true) + or (day_of_week not in (1, 7) and is_weekend != false) \ No newline at end of file diff --git a/tests/singular_tests/dim_date_iso_year_week_logic.sql b/tests/singular_tests/dim_date_iso_year_week_logic.sql new file mode 100644 index 0000000..f6f5b53 --- /dev/null +++ b/tests/singular_tests/dim_date_iso_year_week_logic.sql @@ -0,0 +1,17 @@ +select * +from {{ ref('dim_date') }} +where + ( + date_day = '2021-01-01' + and not (iso_year = 2020 and iso_week_of_year = 53 and year_number = 2021) + ) + or + ( + date_day = '2021-01-04' + and not (iso_year = 2021 and iso_week_of_year = 1 and year_number = 2021) + ) + or + ( + date_day = '2020-12-31' + and not (iso_year = 2020 and iso_week_of_year = 53 and year_number = 2020) + ) \ No newline at end of file