|
| 1 | +{% macro get_fiscal_periods(dates, year_end_month, week_start_day, shift_year=1) %} |
| 2 | +{# |
| 3 | +This macro requires you to pass in a ref to a date dimension, created via |
| 4 | +dbt_date.get_date_dimension()s |
| 5 | +#} |
| 6 | + |
| 7 | +{#- inline version of get_fiscal_year_dates -#} |
| 8 | +-- this gets all the dates within a fiscal year |
| 9 | +-- determined by the given year-end-month |
| 10 | +-- ending on the saturday closest to that month's end date |
| 11 | +with fsc_date_dimension as ( |
| 12 | + select * from {{ dates }} |
| 13 | +), |
| 14 | +year_month_end as ( |
| 15 | + |
| 16 | + select |
| 17 | + d.year_number - {{ shift_year }} as fiscal_year_number, |
| 18 | + d.month_end_date |
| 19 | + from |
| 20 | + fsc_date_dimension d |
| 21 | + where |
| 22 | + d.month_of_year = {{ year_end_month }} |
| 23 | + group by |
| 24 | + d.year_number - {{ shift_year }}, |
| 25 | + d.month_end_date |
| 26 | + |
| 27 | +), |
| 28 | +weeks as ( |
| 29 | + |
| 30 | + select |
| 31 | + d.year_number, |
| 32 | + d.month_of_year, |
| 33 | + d.date_day as week_start_date, |
| 34 | + cast({{ dbt.dateadd('day', 6, 'd.date_day') }} as date) as week_end_date |
| 35 | + from |
| 36 | + fsc_date_dimension d |
| 37 | + where |
| 38 | + d.day_of_week = {{ week_start_day }} |
| 39 | + |
| 40 | +), |
| 41 | +-- get all the weeks that start in the month the year ends |
| 42 | +year_week_ends as ( |
| 43 | + |
| 44 | + select |
| 45 | + d.year_number - {{ shift_year }} as fiscal_year_number, |
| 46 | + d.week_end_date |
| 47 | + from |
| 48 | + weeks d |
| 49 | + where |
| 50 | + d.month_of_year = {{ year_end_month }} |
| 51 | + group by |
| 52 | + d.year_number - {{ shift_year }}, |
| 53 | + d.week_end_date |
| 54 | + |
| 55 | +), |
| 56 | +-- then calculate which Saturday is closest to month end |
| 57 | +weeks_at_month_end as ( |
| 58 | + |
| 59 | + select |
| 60 | + d.fiscal_year_number, |
| 61 | + d.week_end_date, |
| 62 | + m.month_end_date, |
| 63 | + rank() over |
| 64 | + (partition by d.fiscal_year_number |
| 65 | + order by |
| 66 | + abs({{ dbt.datediff('d.week_end_date', 'm.month_end_date', 'day') }}) |
| 67 | + |
| 68 | + ) as closest_to_month_end |
| 69 | + from |
| 70 | + year_week_ends d |
| 71 | + join |
| 72 | + year_month_end m on d.fiscal_year_number = m.fiscal_year_number |
| 73 | +), |
| 74 | +fiscal_year_range as ( |
| 75 | + |
| 76 | + select |
| 77 | + w.fiscal_year_number, |
| 78 | + cast( |
| 79 | + {{ dbt.dateadd('day', 1, |
| 80 | + 'lag(w.week_end_date) over(order by w.week_end_date)') }} |
| 81 | + as date) as fiscal_year_start_date, |
| 82 | + w.week_end_date as fiscal_year_end_date |
| 83 | + from |
| 84 | + weeks_at_month_end w |
| 85 | + where |
| 86 | + w.closest_to_month_end = 1 |
| 87 | + |
| 88 | +), |
| 89 | +fscl_year_dates_for_periods as ( |
| 90 | + |
| 91 | + select |
| 92 | + d.date_day, |
| 93 | + m.fiscal_year_number, |
| 94 | + m.fiscal_year_start_date, |
| 95 | + m.fiscal_year_end_date, |
| 96 | + w.week_start_date, |
| 97 | + w.week_end_date, |
| 98 | + -- we reset the weeks of the year starting with the merch year start date |
| 99 | + dense_rank() |
| 100 | + over( |
| 101 | + partition by m.fiscal_year_number |
| 102 | + order by w.week_start_date |
| 103 | + ) as fiscal_week_of_year |
| 104 | + from |
| 105 | + fsc_date_dimension d |
| 106 | + join |
| 107 | + fiscal_year_range m on d.date_day between m.fiscal_year_start_date and m.fiscal_year_end_date |
| 108 | + join |
| 109 | + weeks w on d.date_day between w.week_start_date and w.week_end_date |
| 110 | + |
| 111 | +), |
| 112 | +{#- end of inline version -#} |
| 113 | + |
| 114 | +fscl_year_w13 as ( |
| 115 | + |
| 116 | + select |
| 117 | + f.*, |
| 118 | + -- We count the weeks in a 13 week period |
| 119 | + -- and separate the 4-5-4 week sequences |
| 120 | + cast( |
| 121 | + (f.fiscal_week_of_year-1) as {{ dbt.type_int() }} |
| 122 | + ) % 13 as w13_number, |
| 123 | + -- Chop weeks into 13 week merch quarters |
| 124 | + cast( |
| 125 | + least( |
| 126 | + floor((f.fiscal_week_of_year-1)/13.0) |
| 127 | + , 3) |
| 128 | + as {{ dbt.type_int() }}) as quarter_number |
| 129 | + from |
| 130 | + fscl_year_dates_for_periods f |
| 131 | + |
| 132 | +), |
| 133 | +fscl_periods as ( |
| 134 | + |
| 135 | + select |
| 136 | + f.date_day, |
| 137 | + f.fiscal_year_number, |
| 138 | + f.week_start_date, |
| 139 | + f.week_end_date, |
| 140 | + f.fiscal_week_of_year, |
| 141 | + case |
| 142 | + -- we move week 53 into the 3rd period of the quarter |
| 143 | + when f.fiscal_week_of_year = 53 then 3 |
| 144 | + when f.w13_number between 0 and 3 then 1 |
| 145 | + when f.w13_number between 4 and 8 then 2 |
| 146 | + when f.w13_number between 9 and 12 then 3 |
| 147 | + end as period_of_quarter, |
| 148 | + f.quarter_number |
| 149 | + from |
| 150 | + fscl_year_w13 f |
| 151 | + |
| 152 | +), |
| 153 | +fscl_periods_quarters as ( |
| 154 | + |
| 155 | + select |
| 156 | + f.*, |
| 157 | + cast(( |
| 158 | + (f.quarter_number * 3) + f.period_of_quarter |
| 159 | + ) as {{ dbt.type_int() }}) as fiscal_period_number |
| 160 | + from |
| 161 | + fscl_periods f |
| 162 | + |
| 163 | +) |
| 164 | +select |
| 165 | + date_day, |
| 166 | + fiscal_year_number, |
| 167 | + week_start_date, |
| 168 | + week_end_date, |
| 169 | + fiscal_week_of_year, |
| 170 | + dense_rank() over(partition by fiscal_period_number order by fiscal_week_of_year) as fiscal_week_of_period, |
| 171 | + fiscal_period_number, |
| 172 | + quarter_number+1 as fiscal_quarter_number, |
| 173 | + period_of_quarter as fiscal_period_of_quarter |
| 174 | +from |
| 175 | + fscl_periods_quarters |
| 176 | +{% endmacro %} |
0 commit comments