PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie kann man in SQL einfach und effizient nach verschachtelten Beziehungen fragen?

Wie bei jeder Abfrage ist die effizienteste Methode "es kommt darauf an". Es spielen viele Variablen eine Rolle - die Anzahl der Zeilen in Tabellen, die Zeilenlänge, ob Indizes vorhanden sind, der Arbeitsspeicher auf dem Server usw. usw.

Der beste Weg, wie ich mir vorstellen kann, diese Art von Problem zu lösen (in Anbetracht der Wartbarkeit und eines breiten Ansatzes für Effizienz), ist die Verwendung von CTEs, mit denen Sie ein temporäres Ergebnis erstellen und dieses Ergebnis in Ihrer Abfrage wiederverwenden können. CTEs verwenden das WITH-Schlüsselwort und aliasieren ein Ergebnis im Wesentlichen als Tabelle, sodass Sie mehrmals mit ihm JOIN können:

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)
;

Die Vorteile dieser Vorgehensweise sind:

  1. Jeder CTE kann einen Index für die entsprechenden JOIN-Prädikate nutzen und Ergebnisse für genau diese Teilmenge schneller zurückgeben, anstatt dass der Ausführungsplaner versucht, eine Reihe komplexer Prädikate aufzulösen
  2. Die CTEs können einzeln gepflegt werden, was die Fehlersuche bei Teilmengen erleichtert
  3. Du verstößt nicht gegen das DRY-Prinzip
  4. Wenn der CTE einen Wert außerhalb der Abfrage hat, können Sie ihn in eine gespeicherte Prozedur verschieben und stattdessen darauf verweisen