Skip to content
Data exploration
Authors
On this page
Published on

Comment savoir si on peut réutiliser un calendrier pour une année donnée en SQL ?

Data exploration
Authors

Executive summary: Comment savoir si on peut réutiliser un calendrier pour une année donnée en SQL ?


Comment savoir si on peut réutiliser un calendrier pour une année donnée en SQL ?

Introduction

Comment on peut réutiliser un calendrier pour une année donnée ?

Et si on essayait de la faire en SQL ?

La logique est la suivante : si le 1er janvier et le 1er mars tombent le même jour de la semaine, alors on peut réutiliser le calendrier de l'année précédente.

On peut donc générer une clé composée de 2 chiffres en base 7 (de 0 à 6) pour chaque année, en fonction du jour de la semaine du 1er janvier et du 1er mars.

En joignant les calendriers de chaque année, on peut alors identifier les années où on peut réutiliser le calendrier de l'année précédente.

Experimentation en DuckDB

sql
SET VARIABLE start_year = '2000';
SET VARIABLE end_year = '2030-12-31'::date;
SET VARIABLE first_jan = concat(getvariable('start_year'), '-01-01')::date;
SET VARIABLE first_march = concat(getvariable('start_year'), '-03-01')::date;

WITH t_january AS (
    SELECT
        YEAR(generate_series) AS current_year,
        DAYOFWEEK(generate_series) AS wday
    FROM generate_series(
        getvariable('first_jan'),
        getvariable('end_year'),
        INTERVAL 1 year
    )
),
t_march AS (
    SELECT
        YEAR(generate_series) AS current_year,
        DAYOFWEEK(generate_series) AS wday
    FROM generate_series(
        getvariable('first_march'),
        getvariable('end_year'),
        INTERVAL 1 year
    )
),
key_by_year AS (
    SELECT
        t_january.current_year,
        concat(t_january.wday, t_march.wday) AS wday_key
    FROM t_january
    JOIN t_march
        ON t_january.current_year = t_march.current_year
),
calendars_joined AS (
    SELECT
        k1.current_year,
        k1.wday_key,
        k2.current_year AS compatible_year,
    FROM key_by_year AS k1
    JOIN key_by_year AS k2
        ON k1.wday_key = k2.wday_key
        AND k1.current_year != k2.current_year
)
SELECT
    current_year,
    array_agg(compatible_year ORDER BY compatible_year) AS same_wday_years
FROM calendars_joined
GROUP BY current_year
ORDER BY current_year;

Et voilà !

current_yearsame_wday_years
2000[2028]
2001[2007, 2018, 2029]
2002[2013, 2019, 2030]
2003[2014, 2025]
2005[2011, 2022]
2006[2017, 2023]
2007[2001, 2018, 2029]
2009[2015, 2026]
2010[2021, 2027]
2011[2005, 2022]
2013[2002, 2019, 2030]
2014[2003, 2025]
2015[2009, 2026]
2017[2006, 2023]
2018[2001, 2007, 2029]
2019[2002, 2013, 2030]
2021[2010, 2027]
2022[2005, 2011]
2023[2006, 2017]
2025[2003, 2014]
2026[2009, 2015]
2027[2010, 2021]
2028[2000]
2029[2001, 2007, 2018]
2030[2002, 2013, 2019]