Génération SQL conditionnelle complexe en Jinja de manière modulaire et documentée


🎯 Objectif

Plutôt que d’avoir une longue chaîne de if dans un modèle dbt, on externalise chaque bloc de logique conditionnelle dans un macro bien nommé, et on ajoute un commentaire clair pour le documenter.


💡 Exemple de cas : filtrer dynamiquement des colonnes selon des flags dans dbt_project.yml ou vars

1. Configuration dans dbt_project.yml ou dbt_profiles.yml

vars:
  include_region_filter: true
  include_product_filter: false

2. Macros modulaires dans macros/filters.sql

-- macros/filters.sql

{% macro region_filter_clause() %}
    -- Inclut le filtre région uniquement si include_region_filter est activé
    {% if var('include_region_filter', false) %}
        AND region = 'Europe'
    {% endif %}
{% endmacro %}

{% macro product_filter_clause() %}
    -- Filtre sur les produits spécifiques si le flag est activé
    {% if var('include_product_filter', false) %}
        AND product_category IN ('Electronics', 'Books')
    {% endif %}
{% endmacro %}

3. Utilisation dans un modèle models/fact_sales.sql

with base as (
    select *
    from {{ ref('stg_sales') }}
    where 1=1
    {{ region_filter_clause() }}
    {{ product_filter_clause() }}
)

select * from base

✅ Avantages

  • Lisibilité accrue : chaque bloc est identifiable par nom et commentaire.
  • Facilité de maintenance : ajouter ou désactiver un filtre ne nécessite pas de modifier tout le modèle.
  • Réutilisable : les macros peuvent être utilisées dans plusieurs modèles.
  • Testable : tu peux ajouter un test unitaire pour chaque macro si besoin.

🔍 Exemple d’évolution facile

Ajout d’un filtre sur l’année dans filters.sql :

{% macro year_filter_clause() %}
    {% if var('filter_year', none) is not none %}
        AND year = {{ var('filter_year') }}
    {% endif %}
{% endmacro %}

Et dans le modèle :

...
where 1=1
    {{ region_filter_clause() }}
    {{ product_filter_clause() }}
    {{ year_filter_clause() }}

Leave a Reply

Your email address will not be published. Required fields are marked *