Concepts SQL pour les jointures

Tout comme en SQL, une jointure en LookML permet de combiner les lignes de deux tables ou plus en fonction d'une colonne associée.

Dans LookML, une exploration, telle que définie par le paramètre LookML explore, permet de définir comment un utilisateur peut interroger les données. Une exploration comprend au moins une vue ou un ensemble de vues jointes. La vue principale de l'exploration est toujours incluse dans la requête. Les vues jointes ne sont normalement incluses que si elles sont nécessaires pour répondre à la requête.

Une vue LookML correspond à une table SQL (ou à un autre élément ayant la structure d'une table) dans la base de données, ou à une table dérivée. La vue définit les champs ou colonnes disponibles dans la base de données, ainsi que leur mode d'accès.

L'exemple suivant est une définition de l'exploration orders.

explore: orders {
  join: users {
    type: left_outer
    sql_on: ${orders.user_id} = ${users.id} ;;
    relationship: many_to_one
  }
}

La vue orders, qui est la vue principale de l'exploration, est jointe à la vue users avec un SQL LEFT OUTER JOIN, comme indiqué par le paramètre LookML type: left_outer. La clause SQL ON, définie par le paramètre LookML sql_on, n'utilise pas table_alias.column, mais fait référence à to ${view_name.field_name}. Ainsi, si le nom de la table ou de la colonne change dans la base de données, cette modification ne doit être effectuée qu'à un seul endroit.

Le paramètre relationship est important. Les jointures peuvent entraîner des problèmes de fanout, c'est-à-dire la duplication de lignes. En spécifiant que de nombreuses commandes ne seront jointes qu'à un seul utilisateur, Looker reconnaît que cette jointure ne générera pas de fanouts. Aucune gestion spéciale n'est donc nécessaire. Toutefois, les relations one_to_many peuvent déclencher un fanout.

La génération automatique de vues et d'explorations utilise par défaut une jointure externe gauche. Dans l'exemple précédent, cependant, il est très probable que chaque commande corresponde à un seul utilisateur. La jointure dans cet exemple peut donc être une jointure interne.

Pour afficher le code SQL généré d'une exploration, vous pouvez exécuter l'exploration dans l'interface utilisateur, puis sélectionner l'onglet SQL dans le panneau Données.

Par exemple, si vous ouvrez l'exploration Commandes, définie précédemment, puis sélectionnez les champs ID utilisateur et Nombre, la requête SQL générée se présente comme suit:

SELECT
    `user_id` AS `orders.user_id`,
    COUNT(*) AS `orders.count`
FROM
    `thelook`.`orders` AS `orders`
GROUP BY
    1
ORDER BY
    2 DESC
LIMIT 500

Dans cet exemple, la table "users" n'est pas référencée du tout. Il n'est importé que si nécessaire.

Si vous supprimez la dimension ID utilisateur et ajoutez la dimension ID à la vue Utilisateurs, la requête SQL se présente comme suit:

SELECT
    `users`.`id` AS `users.id`,
    COUNT(*) AS `orders.count`
FROM
    `thelook`.`orders` AS `orders`
    INNER JOIN `thelook`.`users` AS `users` ON `orders`.`user_id` = `users`.`id`
GROUP BY
    1
ORDER BY
    2 DESC
LIMIT 500

Dans ce cas, comme une sélection a été effectuée dans la vue Utilisateurs, la jointure est incluse.

L'exemple suivant montre LookML dans le fichier d'exploration orders, qui a été défini précédemment, et ajoute une jointure à la vue order_items:

explore: orders {
  join: users {
    type: inner
    sql_on: ${orders.user_id} = ${users.id} ;;
    relationship: many_to_one
  }
  join: order_items {
    type: inner
    sql_on: ${orders.id} = ${order_items.order_id} ;;
    relationship: one_to_many
  }
}

Si vous ouvrez l'exploration Commandes dans l'interface utilisateur, la vue Éléments de commande s'affiche. Si vous sélectionnez la mesure Prix de vente total dans la vue Éléments de commande, ainsi que le nombre Count dans Commandes et l'ID ID dans Utilisateurs, Looker génère la requête SQL suivante:

SELECT
    `users`.`id` AS `users.id`,
    COUNT(DISTINCT orders.id ) AS `orders.count`,
    COALESCE(SUM(`order_items`.`sale_price`), 0) AS `order_items.total_sale_price`
FROM
    `thelook`.`orders` AS `orders`
    INNER JOIN `thelook`.`users` AS `users` ON `orders`.`user_id` = `users`.`id`
    INNER JOIN `thelook`.`order_items` AS `order_items` ON `orders`.`id` = `order_items`.`order_id`
GROUP BY
    1
ORDER BY
    2 DESC
LIMIT 500

Dans cet exemple, COUNT(*) AS orders.count est devenu COUNT(DISTINCT orders.id ) AS orders.count. Looker a détecté une situation de fanout possible et a automatiquement ajouté le mot clé SQL DISTINCT à la fonction SQL COUNT.