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 satisfaire la requête.

Une vue LookML correspond à une table SQL (ou à un autre élément ayant la structure d'une table) de 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 distribution ramifiée en cas de doublons 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 une distribution ramifiée.

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 Orders (Commandes) définie précédemment, puis que vous sélectionnez les champs User ID (ID utilisateur) et Count (Nombre), le code SQL généré 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 des utilisateurs n'est pas référencée du tout. Il n'est utilisé 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, 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'interface utilisateur, vous accédez à la vue Order Items (Articles de la commande). Si vous sélectionnez la mesure Total Sale price (Prix total de vente) dans la vue Order Items (Articles de commande), ainsi que le nombre de commandes Orders (Commandes) et l'ID (ID) provenant des 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.