Les jointures dans Lightdash permettent aux utilisateurs de combiner des dimensions et des métriques provenant de plusieurs modèles dbt dans une seule requête Explore. Sans jointures, chaque modèle est une île isolée — les utilisateurs ne peuvent analyser que les dimensions et métriques qui résident sur le même modèle. Avec des jointures, un modèle d’ordres peut intégrer des attributs clients depuis un modèle CRM, des données de campagne depuis un modèle marketing, ou des détails produits depuis un modèle catalogue, le tout dans une seule requête sans que personne n’écrive du SQL.
Définir une jointure
Les jointures se placent sous meta.joins au niveau du modèle :
models: - name: mrt__sales__orders meta: primary_key: order__id joins: - join: mrt__crm__customers sql_on: > ${mrt__sales__orders.customer__id} = ${mrt__crm__customers.customer__id} relationship: many-to-one type: leftLa clause sql_on utilise la syntaxe de référence de dimension de Lightdash : ${model_name.column_name}. Il s’agit d’un template Jinja-like qui est compilé en condition de jointure SQL réelle. L’utilisation de références de dimension plutôt que de noms de colonnes bruts signifie que la jointure respecte tout alias de colonne ou surcharge de schéma que vous avez configuré.
Le type est left par défaut si omis. Les quatre options sont inner, left, right et full. Les jointures left sont le bon choix par défaut pour la plupart des cas d’usage BI — vous souhaitez toutes les lignes du modèle principal, avec des nulls là où le modèle joint n’a pas de correspondance, plutôt que de supprimer silencieusement les lignes non correspondantes.
La propriété relationship et son utilité
La propriété relationship n’est pas cosmétique. Lightdash l’utilise pour déterminer quelles métriques du modèle joint sont sûres à utiliser.
Les options sont many-to-one, one-to-one et one-to-many. Une mauvaise configuration est l’une des sources les plus courantes de métriques gonflées dans les outils BI.
Voici le problème : dans une jointure one-to-many, chaque ligne du modèle principal correspond à plusieurs lignes du modèle joint. Cela provoque une duplication de lignes côté modèle principal. Toute métrique qui somme ou compte des lignes du modèle principal sera gonflée par le facteur de multiplication.
Prenons un modèle d’ordres joint à un modèle de line_items (un ordre, plusieurs lignes). Si vous calculez total_revenue (une somme sur le modèle d’ordres) via cette jointure, chaque ligne d’ordre est comptée une fois pour chaque ligne qu’elle contient. Un ordre avec cinq lignes contribue cinq fois à la somme. Le résultat est faux.
Lightdash utilise la propriété relationship pour signaler ce risque. Dans une jointure one-to-many :
- Signalées comme risquées : les métriques
sum,average,countdu modèle principal - Sûres à utiliser :
min,max,count_distinctdu modèle principal
Lightdash avertit les utilisateurs avant d’exécuter une requête combinant une métrique signalée avec une dimension jointe en one-to-many. L’avertissement ne bloque pas la requête — les utilisateurs peuvent continuer — mais il rend le risque visible au moment de l’analyse plutôt qu’après.
joins: - join: mrt__sales__line_items sql_on: > ${mrt__sales__orders.order__id} = ${mrt__sales__line_items.order__id} relationship: one-to-many # triggers fanout warnings on sum/count metrics type: leftLa bonne correction pour ce pattern réside généralement dans les modèles dbt eux-mêmes : si vous avez besoin de métriques au niveau ordre et de dimensions de lignes ensemble, construisez un mart qui les pré-join à la bonne granularité plutôt que de vous appuyer sur une jointure à l’exécution. Mais lorsqu’une jointure à l’exécution est véritablement nécessaire, la propriété relationship rend au moins le risque visible.
Propriétés de jointure supplémentaires
fields
Autorise une liste spécifique de dimensions ou métriques depuis le modèle joint. Par défaut, tous les champs non masqués du modèle joint apparaissent dans la barre latérale Explore. fields restreint cela à ce qui est utile :
joins: - join: mrt__crm__customers sql_on: > ${mrt__sales__orders.customer__id} = ${mrt__crm__customers.customer__id} relationship: many-to-one type: left fields: - customer__name - customer__segment - customer__countryC’est particulièrement utile pour les grands modèles. Si votre modèle clients a 40 colonnes mais que vous n’en avez besoin que de 3 dans le contexte de l’Explore des ordres, exposer les 40 crée une barre latérale encombrée et expose des colonnes qui peuvent ne pas avoir de sens quand elles sont consultées via le prisme des ordres.
hidden
hidden: true joint le modèle sans l’exposer dans la barre latérale. La jointure s’exécute quand même — les colonnes du modèle joint deviennent disponibles pour le filtrage — mais les utilisateurs ne peuvent pas voir ni sélectionner ses dimensions comme champs explicites :
joins: - join: mrt__access__user_permissions sql_on: > ${mrt__sales__orders.customer__id} = ${mrt__access__user_permissions.user__id} relationship: many-to-one type: inner hidden: trueLe cas d’usage ici est le filtrage au niveau ligne. Une jointure masquée vers un modèle de permissions peut garantir que les utilisateurs ne voient que les données auxquelles ils sont autorisés, sans exposer le modèle de permissions comme une entité navigable dans la vue Explore.
alias
Renomme le modèle joint quand le même modèle doit apparaître deux fois :
joins: - join: mrt__crm__contacts alias: billing_contact sql_on: > ${mrt__sales__orders.billing_contact__id} = ${billing_contact.contact__id} relationship: many-to-one type: left - join: mrt__crm__contacts alias: shipping_contact sql_on: > ${mrt__sales__orders.shipping_contact__id} = ${shipping_contact.contact__id} relationship: many-to-one type: leftSans alias, vous ne pouvez pas joindre le même modèle deux fois — la seconde jointure n’aurait aucun moyen de se distinguer de la première. Avec les alias, les deux jointures utilisent des noms différents, et leurs champs apparaissent comme des sections séparées dans la barre latérale (billing_contact.* et shipping_contact.*).
Quand utiliser les jointures vs. les marts plus larges
La tension dans la conception BI : faut-il tout pré-joindre dans un mart large, ou garder des modèles étroits et utiliser des jointures au niveau BI ?
Les marts pré-joints sont plus performants (la jointure s’exécute une fois au moment de la transformation, pas à chaque requête), et il n’y a pas de risque de fanout à gérer. Ce sont le bon choix quand une jointure est fréquente, la cardinalité est stable, et la granularité combinée a du sens sémantiquement comme entité unique.
Les jointures au niveau BI sont meilleures pour l’exploration ad-hoc — quand vous avez occasionnellement besoin de combiner deux modèles qui ne vont pas toujours ensemble, ou quand le produit croisé de combinaisons nécessiterait trop de marts pré-construits. Les avertissements de fanout de Lightdash rendent les jointures ad-hoc plus sûres que dans un outil sans conscience des relations.
La heuristique pratique : si les analystes joignent constamment les modèles A et B dans la vue Explore, c’est un signal pour pré-construire cette jointure dans dbt. S’ils joignent A et B occasionnellement, pour des analyses spécifiques, la jointure Explore est le bon choix. Réservez la couche mart aux combinaisons stables et fréquemment utilisées ; laissez les jointures Lightdash gérer les cas d’usage exploratoires ponctuels.