Concepts SQL pour les jointures

Comme en SQL, une jointure dans LookML est utilisée pour combiner les lignes de deux tables ou plus, en fonction d'une colonne associée entre elles.

Dans LookML, une exploration, telle que définie par le paramètre LookML explore, permet de définir la façon dont 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'onglet "Explorer" 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 façon d'y accéder.

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 une 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, il ne doit être modifié qu'à un seul endroit.

Le paramètre relationship est important. Les jointures peuvent entraîner des problèmes de fan-out, où les lignes sont dupliquées. En spécifiant que plusieurs commandes seront associées à un seul utilisateur, Looker reconnaît qu'aucun fan-out 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 une expansion.

La génération automatique de vues et d'Explores utilise par défaut une jointure externe gauche. Toutefois, dans l'exemple précédent, il est très probable que chaque commande n'ait qu'un seul utilisateur. La jointure 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'UI, 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, 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 du tout. Il n'est intégré que si nécessaire.

Si vous supprimez la dimension ID utilisateur et ajoutez la dimension ID à partir de la vue Utilisateurs, la requête 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 a été effectuée dans la vue Utilisateurs, la jointure est incluse.

L'exemple suivant montre le LookML dans le fichier Explorer 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'UI, vous verrez la vue Articles de la commande. Si vous sélectionnez la mesure Prix de vente total dans la vue Éléments de commande, ainsi que Nombre dans Commandes et ID dans 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 fan-out potentielle et a automatiquement ajouté le mot clé SQL DISTINCT à la fonction SQL COUNT.