PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment interroger simplement et efficacement les relations imbriquées en SQL ?

Comme pour toute requête, la méthode la plus efficace est "ça dépend". De nombreuses variables sont en jeu :le nombre de lignes dans les tables, la longueur des lignes, l'existence d'index, la RAM sur le serveur, etc.

La meilleure façon de gérer ce type de problème (en pensant à la maintenabilité et à une approche globale de l'efficacité) consiste à utiliser les CTE, qui vous permettent de créer un résultat temporaire et de le réutiliser tout au long de votre requête. Les CTE utilisent le mot-clé WITH, et alias essentiellement un résultat en tant que table, de sorte que vous pouvez vous JOINDRE plusieurs fois :

WITH user_memberships AS (
    SELECT *
    FROM memberships
    WHERE user_id = ${id}
), user_apps AS (
    SELECT *
    FROM apps
    INNER JOIN user_memberships
        ON user_memberships.team_id = apps.team_id
), user_collections AS (
    SELECT *
    FROM collections
    INNER JOIN user_memberships
        ON user_memberships.team_id = collections.team_id
), user_webhooks AS (
    SELECT *
    FROM webhooks
    LEFT OUTER JOIN user_collections ON user_collections.id = webhooks.collection_id
    INNER JOIN user_memberships
        ON user_memberships.team_id = webhooks.team_id
        OR user_memberships.team_id = user_collections.team_id
)

SELECT events.* 
FROM events
WHERE app_id IN (SELECT id FROM user_apps)
OR collection_id IN (SELECT id FROM user_collections)
OR membership_id IN (SELECT id FROM user_memberships)
OR team_id IN (SELECT team_id FROM user_memberships)
OR user_id = ${id}
OR webhook_id IN (SELECT id FROM user_webhooks)
;

Les avantages de procéder ainsi sont :

  1. Chaque CTE peut tirer parti d'un index sur les prédicats JOIN appropriés et renvoyer les résultats pour ce sous-ensemble plus rapidement, plutôt que de laisser le planificateur d'exécution tenter de résoudre une série de prédicats complexes
  2. Les CTE peuvent être gérés individuellement, ce qui facilite la résolution des problèmes de sous-ensembles
  3. Vous n'enfreignez pas le principe DRY
  4. Si le CTE a une valeur en dehors de la requête, vous pouvez le déplacer dans une procédure stockée et la référencer à la place