fiscal_date_dim.sql (432 lines of code) (raw):

#-- Copyright 2023 Google LLC #-- #-- Licensed under the Apache License, Version 2.0 (the "License"); #-- you may not use this file except in compliance with the License. #-- You may obtain a copy of the License at #-- #-- https://www.apache.org/licenses/LICENSE-2.0 #-- #-- Unless required by applicable law or agreed to in writing, software #-- distributed under the License is distributed on an "AS IS" BASIS, #-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #-- See the License for the specific language governing permissions and #-- limitations under the License. --## CORTEX-CUSTOMER: The fiscal table solution works only for those variants(periv) -- where we have fiscal year as a continuous calendar year. Consider commenting/uncommenting -- a specific fiscal case as per your requirement. --CASE 1: If t009.xkale = 'X', Fiscal year is the same as calendar year. ( SELECT mandt, periv, dt AS Date, CAST(FORMAT_DATE('%Y%m%d', dt) AS INT64) AS DateInt, FORMAT_DATE('%Y%m%d', dt) AS DateStr, FORMAT_DATE('0%m', dt) AS FiscalPeriod, FORMAT_DATE('%Y', dt) AS FiscalYear, FORMAT_DATE('%Y0%m', dt) AS FiscalYearPeriod, DATE_TRUNC(dt, YEAR) AS FiscalYearFirstDay, LAST_DAY(dt, YEAR) AS FiscalYearLastDay, IF(EXTRACT(QUARTER FROM dt) IN (1, 2), 1, 2) AS FiscalSemester, IF(EXTRACT(QUARTER FROM dt) IN (1, 2), '01', '02') AS FiscalSemesterStr, IF(EXTRACT(QUARTER FROM dt) IN (1, 2), '1st Semester', '2nd Semester') AS FiscalSemesterStr2, EXTRACT(QUARTER FROM dt) AS FiscalQuarter, '0' || EXTRACT(QUARTER FROM dt) AS FiscalQuarterStr, 'Q' || EXTRACT(QUARTER FROM dt) AS FiscalQuarterStr2, EXTRACT(WEEK FROM dt) AS FiscalWeek, '0' || EXTRACT(WEEK FROM dt) AS FiscalWeekStr, DATE_TRUNC(dt, WEEK) AS WeekStartDate, LAST_DAY(dt, WEEK) AS WeekEndDate, FORMAT_DATE('%A', dt) AS DayNameLong, FORMAT_DATE('%a', dt) AS DayNameShort FROM `{{ project_id_src }}.{{ dataset_cdc_processed }}.t009`, UNNEST( GENERATE_DATE_ARRAY( DATE_SUB(DATE_TRUNC(CURRENT_DATE(), YEAR), INTERVAL 10 YEAR), DATE_ADD(LAST_DAY(CURRENT_DATE(), YEAR), INTERVAL 10 YEAR), INTERVAL 1 DAY) ) AS dt WHERE xkale = 'X' AND mandt = '{{ mandt }}' ) UNION ALL --CASE 2: If t009.xjabh = 'X', Fiscal year is not a calendar year and has fiscal variants. ( WITH -- Calculate end date for each fiscal year and period combination. GetEndDate AS ( SELECT t009.mandt, t009.periv, t009b.bdatj, t009b.bumon, t009b.butag, t009b.reljr, t009b.poper, CAST(MIN(t009b.bumon) OVER (PARTITION BY t009.mandt, t009.periv, t009b.bdatj) AS INT64) AS MinimumBumon, CAST(CONCAT(t009b.bdatj, '-', t009b.bumon, '-', t009b.butag) AS DATE) AS EndDate FROM `{{ project_id_src }}.{{ dataset_cdc_processed }}.t009` AS t009 INNER JOIN `{{ project_id_src }}.{{ dataset_cdc_processed }}.t009b` AS t009b ON t009.mandt = t009b.mandt AND t009.periv = t009b.periv WHERE t009.xjabh = 'X' AND t009.mandt = '{{ mandt }}' ), -- Calculate start date according to fiscal year and period combination. GetStartDate AS ( SELECT mandt, periv, bdatj, bumon, butag, reljr, poper, EndDate, -- Calculate start date based on end date. COALESCE( DATE_ADD( LAG(EndDate) OVER (PARTITION BY mandt, periv ORDER BY bdatj, bumon, butag), INTERVAL 1 DAY), DATE_TRUNC(EndDate, MONTH) ) AS StartDate FROM GetEndDate ), -- Calculate Fiscal Year First and Last Day. GetFirstAndLastDay AS ( SELECT mandt, periv, poper, dt, MIN(dt) OVER (PARTITION BY mandt, periv, CAST(bdatj AS INT64) + CAST(reljr AS INT64)) AS FiscalYearFirstDay, MAX(dt) OVER (PARTITION BY mandt, periv, CAST(bdatj AS INT64) + CAST(reljr AS INT64)) AS FiscalYearLastDay, LAST_DAY(dt, WEEK) AS WeekEndDate, DATE_TRUNC(dt, WEEK) AS WeekStartDate, CAST(bdatj AS INT64) + CAST(reljr AS INT64) AS FiscalYear FROM GetStartDate, UNNEST(GENERATE_DATE_ARRAY(StartDate, EndDate)) AS dt ), -- Calculate aggregated fields, i.e, FiscalSemester,FiscalWeek and FiscalQuarter. GetAggFields AS ( SELECT mandt, periv, dt AS Date, FiscalYearFirstDay, FiscalYearLastDay, FiscalYear AS FiscalYearInt, WeekStartDate, WeekEndDate, poper AS FiscalPeriod, CAST(FiscalYear AS STRING) AS FiscalYear, CAST(FORMAT_DATE('%Y%m%d', dt) AS INT64) AS DateInt, FORMAT_DATE('%Y%m%d', dt) AS DateStr, CASE WHEN dt >= FiscalYearFirstDay AND dt < DATE_ADD(FiscalYearFirstDay, INTERVAL 6 MONTH) THEN 1 WHEN dt >= DATE_ADD(FiscalYearFirstDay, INTERVAL 6 MONTH) AND dt <= FiscalYearLastDay THEN 2 END AS FiscalSemester, CASE WHEN dt >= FiscalYearFirstDay AND dt < DATE_ADD(FiscalYearFirstDay, INTERVAL 3 MONTH) THEN 1 WHEN dt >= DATE_ADD(FiscalYearFirstDay, INTERVAL 3 MONTH) AND dt < DATE_ADD(FiscalYearFirstDay, INTERVAL 6 MONTH) THEN 2 WHEN dt >= DATE_ADD(FiscalYearFirstDay, INTERVAL 6 MONTH) AND dt < DATE_ADD(FiscalYearFirstDay, INTERVAL 9 MONTH) THEN 3 WHEN dt >= DATE_ADD(FiscalYearFirstDay, INTERVAL 9 MONTH) AND dt <= FiscalYearLastDay THEN 4 END AS FiscalQuarter, CAST( IF( FORMAT_DATE('%A', FiscalYearFirstDay) = 'Sunday', CEIL(SAFE_DIVIDE(DATE_DIFF(WeekEndDate, FiscalYearFirstDay, DAY), 7)), FLOOR(SAFE_DIVIDE(DATE_DIFF(WeekEndDate, FiscalYearFirstDay, DAY), 7)) ) AS INT64) AS FiscalWeek, FORMAT_DATE('%A', dt) AS DayNameLong, FORMAT_DATE('%a', dt) AS DayNameShort, CONCAT(FiscalYear, poper) AS FiscalYearPeriod FROM GetFirstAndLastDay ) SELECT mandt, periv, Date, DateInt, DateStr, FiscalPeriod, FiscalYear, FiscalYearPeriod, FiscalYearFirstDay, FiscalYearLastDay, FiscalSemester, CAST(CONCAT(0, FiscalSemester) AS STRING) AS FiscalSemesterStr, IF(FiscalSemester = 1, '1st Semester', '2nd Semester') AS FiscalSemesterStr2, FiscalQuarter, CAST(CONCAT(0, FiscalQuarter) AS STRING) AS FiscalQuarterStr, CAST(CONCAT('Q', FiscalQuarter) AS STRING) AS FiscalQuarterStr2, FiscalWeek, LPAD(CAST(FiscalWeek AS STRING), 2, '0') AS FiscalWeekStr, WeekStartDate, WeekEndDate, DayNameLong, DayNameShort FROM GetAggFields ) UNION ALL --CASE 3: If t009.xkale IS NULL AND t009.xjabh IS NULL, --Indicates that the fiscal calendar is grouped into custom fiscal variants. --It has two scenarios, i.e, t009b.bdatj = '0000' and t0009b.bdatj != '0000'. ( WITH -- Calculate end date for each fiscal year and period combination for t009b.bdatj = '0000' GetEndDateForFirstScenario AS ( SELECT t009.mandt, t009.periv, cal_year AS bdatj, t009b.bumon, t009b.butag, t009b.reljr, t009b.poper, CAST(MIN(t009b.bumon) OVER (PARTITION BY t009.mandt, t009.periv) AS INT64) AS MinimumBumon, SUBSTR( MIN(CONCAT(t009b.poper, '-', t009b.bumon, '-', t009b.butag)) OVER (PARTITION BY t009.mandt, t009.periv), 5) AS MinimumPeriod, SUBSTR( MAX(CONCAT(t009b.poper, '-', t009b.bumon, '-', t009b.butag)) OVER (PARTITION BY t009.mandt, t009.periv), 5) AS MaximumPeriod, --If the year is not a leap year,updating end date for Feb as '28 Feb' CASE WHEN NOT `{{ project_id_tgt }}.{{ dataset_reporting_tgt }}.is_leap_year`(cal_year) AND t009b.bumon = '02' AND t009b.butag = '29' THEN CAST(CONCAT(cal_year, '-', t009b.bumon, '-28') AS DATE) ELSE CAST(CONCAT(cal_year, '-', t009b.bumon, '-', t009b.butag) AS DATE) END AS EndDate FROM `{{ project_id_src }}.{{ dataset_cdc_processed }}.t009` AS t009 INNER JOIN `{{ project_id_src }}.{{ dataset_cdc_processed }}.t009b` AS t009b ON t009.mandt = t009b.mandt AND t009.periv = t009b.periv, UNNEST( GENERATE_ARRAY( EXTRACT(YEAR FROM DATE_SUB(CURRENT_DATE(), INTERVAL 10 YEAR)), EXTRACT(YEAR FROM DATE_ADD(CURRENT_DATE(), INTERVAL 10 YEAR)) )) AS cal_year WHERE t009.mandt = '{{ mandt }}' AND t009.xkale IS NULL AND t009.xjabh IS NULL AND t009b.bdatj = '0000' ), -- Calculate start date according to fiscal year and period combination for t009b.bdatj = '0000' GetStartDateForFirstScenario AS ( SELECT mandt, periv, bdatj, bumon, butag, reljr, poper, EndDate, MinimumBumon, CAST(bdatj AS INT64) + CAST(reljr AS INT64) AS FiscalYear, MIN(reljr) OVER (PARTITION BY mandt, periv) AS MinimumReljr, -- If the year is not a leap year,updating min period for Feb as '28 Feb' IF( NOT `{{ project_id_tgt }}.{{ dataset_reporting_tgt }}.is_leap_year`(bdatj) AND MinimumPeriod = '02-29', REPLACE(MinimumPeriod, '29', '28'), MinimumPeriod) AS MinimumPeriod, -- If the year is not a leap year,updating max period for Feb as '28 Feb' IF( NOT `{{ project_id_tgt }}.{{ dataset_reporting_tgt }}.is_leap_year`(bdatj) AND MaximumPeriod = '02-29', REPLACE(MaximumPeriod, '29', '28'), MaximumPeriod) AS MaximumPeriod, -- Calculate start date accordingly in case fiscal period is greater than 1 month. IF( MinimumBumon = 01, COALESCE( DATE_ADD( LAG(EndDate) OVER (PARTITION BY mandt, periv ORDER BY bdatj, bumon, butag), INTERVAL 1 DAY), DATE_TRUNC(EndDate, MONTH)), DATE_SUB(DATE_TRUNC(EndDate, MONTH), INTERVAL (MinimumBumon - 1) MONTH) ) AS StartDate FROM GetEndDateForFirstScenario ), -- Calculate Fiscal Year First and Last Day. GetFirstAndLastDayForFirstScenario AS ( SELECT mandt, periv, poper, dt, reljr, FiscalYear, -- Fiscal Year First Day is calculated according to reljr, if reljr is '+ year', -- fiscal year starts in previous calendar year based on the reljr. -- For remaining two cases of reljr, fiscal year starts in the same year as of calendar year. DATE_SUB( DATE_TRUNC( CAST( CASE WHEN MinimumReljr = '0' THEN CONCAT(FiscalYear, '-', MinimumPeriod) WHEN SUBSTR(MinimumReljr, 1, 1) = '+' THEN CONCAT(FiscalYear - CAST(SUBSTR(MinimumReljr, 2, 1) AS INT64), '-', MinimumPeriod) WHEN SUBSTR(MinimumReljr, 1, 1) = '-' THEN CONCAT(FiscalYear, '-', MinimumPeriod) END AS DATE), MONTH), INTERVAL (MinimumBumon - 1) MONTH) AS FiscalYearFirstDay, -- Fiscal Year Last Day is calculated according to reljr, if reljr is '- year', -- fiscal year ends in next calendar year based on the reljr. -- For remaining two cases of reljr, fiscal year ends in the same year as of calendar year. CAST( CASE WHEN MinimumReljr = '0' THEN CONCAT(FiscalYear, '-', MaximumPeriod) WHEN SUBSTR(MinimumReljr, 1, 1) = '+' THEN CONCAT(FiscalYear, '-', MaximumPeriod) WHEN SUBSTR(MinimumReljr, 1, 1) = '-' THEN CONCAT(FiscalYear + CAST(SUBSTR(MinimumReljr, 2, 1) AS INT64), '-', MaximumPeriod) END AS DATE) AS FiscalYearLastDay, DATE_TRUNC(dt, WEEK) AS WeekStartDate, LAST_DAY(dt, WEEK) AS WeekEndDate FROM GetStartDateForFirstScenario, UNNEST(GENERATE_DATE_ARRAY(StartDate, EndDate)) AS dt ), -- Calculate end date for each fiscal year and period combination for t009b.bdatj != '0000' GetEndDateForSecondScenario AS ( SELECT t009.mandt, t009.periv, t009b.bdatj, t009b.bumon, t009b.butag, t009b.reljr, t009b.poper, CAST(MIN(t009b.bumon) OVER (PARTITION BY t009.mandt, t009.periv, t009b.bdatj) AS INT64) AS MinimumBumon, CAST(CONCAT(t009b.bdatj, '-', t009b.bumon, '-', t009b.butag) AS DATE) AS EndDate FROM `{{ project_id_src }}.{{ dataset_cdc_processed }}.t009` AS t009 INNER JOIN `{{ project_id_src }}.{{ dataset_cdc_processed }}.t009b` AS t009b ON t009.mandt = t009b.mandt AND t009.periv = t009b.periv WHERE t009.xkale IS NULL AND t009.xjabh IS NULL AND t009.mandt = '{{ mandt }}' AND t009b.bdatj != '0000' ), -- Calculate start date according to fiscal year and period combination for t009b.bdatj != '0000' GetStartDateForSecondScenario AS ( SELECT mandt, periv, bdatj, bumon, butag, reljr, poper, EndDate, -- Calculate start date accordingly in case fiscal period is greater than 1 month. IF( MinimumBumon = 01, COALESCE( DATE_ADD( LAG(EndDate) OVER (PARTITION BY mandt, periv ORDER BY bdatj, bumon, butag), INTERVAL 1 DAY), DATE_TRUNC(EndDate, MONTH)), DATE_SUB(DATE_TRUNC(EndDate, MONTH), INTERVAL (MinimumBumon - 1) MONTH) ) AS StartDate FROM GetEndDateForSecondScenario ), -- Calculate Fiscal Year First and Last Day. GetFirstAndLastDayForSecondScenario AS ( SELECT mandt, periv, poper, dt, reljr, CAST(bdatj AS INT64) + CAST(reljr AS INT64) AS FiscalYear, MIN(dt) OVER (PARTITION BY mandt, periv, CAST(bdatj AS INT64) + CAST(reljr AS INT64)) AS FiscalYearFirstDay, MAX(dt) OVER (PARTITION BY mandt, periv, CAST(bdatj AS INT64) + CAST(reljr AS INT64)) AS FiscalYearLastDay, DATE_TRUNC(dt, WEEK) AS WeekStartDate, LAST_DAY(dt, WEEK) AS WeekEndDate FROM GetStartDateForSecondScenario, UNNEST(GENERATE_DATE_ARRAY(StartDate, EndDate)) AS dt ), --Combining the records of both scenarios, i.e, t009b.bdatj ='0000' and t009b.bdatj != '0000' CombineBothScenarios AS ( SELECT * FROM GetFirstAndLastDayForFirstScenario UNION ALL SELECT * FROM GetFirstAndLastDayForSecondScenario ), -- Calculate aggregated fields, i.e, FiscalSemester,FiscalWeek and FiscalQuarter. GetAggFields AS ( SELECT mandt, periv, dt AS Date, FiscalYearFirstDay, FiscalYearLastDay, WeekStartDate, WeekEndDate, poper AS FiscalPeriod, CAST(FiscalYear AS STRING) AS FiscalYear, CAST(FORMAT_DATE('%Y%m%d', dt) AS INT64) AS DateInt, FORMAT_DATE('%Y%m%d', dt) AS DateStr, CASE WHEN dt >= FiscalYearFirstDay AND dt < DATE_ADD(FiscalYearFirstDay, INTERVAL 6 MONTH) THEN 1 WHEN dt >= DATE_ADD(FiscalYearFirstDay, INTERVAL 6 MONTH) AND dt <= FiscalYearLastDay THEN 2 END AS FiscalSemester, CASE WHEN dt >= FiscalYearFirstDay AND dt < DATE_ADD(FiscalYearFirstDay, INTERVAL 3 MONTH) THEN 1 WHEN dt >= DATE_ADD(FiscalYearFirstDay, INTERVAL 3 MONTH) AND dt < DATE_ADD(FiscalYearFirstDay, INTERVAL 6 MONTH) THEN 2 WHEN dt >= DATE_ADD(FiscalYearFirstDay, INTERVAL 6 MONTH) AND dt < DATE_ADD(FiscalYearFirstDay, INTERVAL 9 MONTH) THEN 3 WHEN dt >= DATE_ADD(FiscalYearFirstDay, INTERVAL 9 MONTH) AND dt <= FiscalYearLastDay THEN 4 END AS FiscalQuarter, IF( FORMAT_DATE('%A', FiscalYearFirstDay) = 'Sunday', CAST(CEIL(SAFE_DIVIDE(DATE_DIFF(WeekEndDate, FiscalYearFirstDay, DAY), 7)) AS INT64), CAST(FLOOR(SAFE_DIVIDE(DATE_DIFF(WeekEndDate, FiscalYearFirstDay, DAY), 7)) AS INT64) ) AS FiscalWeek, FORMAT_DATE('%A', dt) AS DayNameLong, FORMAT_DATE('%a', dt) AS DayNameShort, CONCAT(FiscalYear, poper) AS FiscalYearPeriod FROM CombineBothScenarios ) SELECT mandt, periv, Date, DateInt, DateStr, FiscalPeriod, FiscalYear, FiscalYearPeriod, FiscalYearFirstDay, FiscalYearLastDay, FiscalSemester, CAST(CONCAT(0, FiscalSemester) AS STRING) AS FiscalSemesterStr, IF(FiscalSemester = 1, '1st Semester', '2nd Semester') AS FiscalSemesterStr2, FiscalQuarter, CAST(CONCAT(0, FiscalQuarter) AS STRING) AS FiscalQuarterStr, CAST(CONCAT('Q', FiscalQuarter) AS STRING) AS FiscalQuarterStr2, FiscalWeek, LPAD(CAST(FiscalWeek AS STRING), 2, '0') AS FiscalWeekStr, WeekStartDate, WeekEndDate, DayNameLong, DayNameShort FROM GetAggFields --## CORTEX-CUSTOMER: The fiscal table solution works for only those variants(periv) -- where we have fiscal year as a continuous calendar year. WHERE periv NOT IN ('C2') )