Concepts SQL pour les jointures

Comme en SQL, une jointure dans LookML permet de combiner les lignes de plusieurs tables en fonction des colonnes qu'elles ont en commun.

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 se compose d'au moins une vue ou d'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 et la manière dont ils doivent être consulté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, où les lignes sont dupliquées. En spécifiant que de nombreuses commandes ne seront jointes qu'à un seul utilisateur, Looker reconnaît qu'aucun fanout ne se produira à partir de cette jointure. 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 est définie par défaut sur une jointure externe gauche. Dans l'exemple précédent, il est toutefois très probable que chaque commande n'ait qu'un seul utilisateur. La jointure de cet exemple peut donc être une jointure interne.

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

Par exemple, si vous ouvrez l'exploration Orders (Commandes), définie précédemment, puis sélectionnez les champs User ID (ID utilisateur) et Count (Nombre), le code SQL généré se présentera 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. Elle n'est incluse que si elle est nécessaire.

Si vous supprimez la dimension User ID (ID utilisateur) et ajoutez la dimension ID à partir de la vue Users (Utilisateurs), le code SQL se présentera 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 est effectuée à partir de la vue Users (Utilisateurs), la jointure est incluse.

L'exemple suivant montre le code LookML dans le fichier d'exploration orders, 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 Orders (Commandes) dans l'UI, la vue Order Items (Articles de la commande) s'affiche. Si vous sélectionnez la mesure Total Sale Price (Prix de vente total) dans la vue Order Items (Articles de la commande), ainsi que le Count (Nombre) dans Orders (Commandes) et l'ID dans Users (Utilisateurs), Looker génère le code SQL suivant :

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.