sql >> Database >  >> RDS >> PostgreSQL

Hoe eenvoudig en efficiënt zoeken naar geneste relaties in SQL?

Zoals bij elke zoekopdracht, is de meest efficiënte methode "het hangt ervan af". Er zijn veel variabelen in het spel - het aantal rijen in tabellen, de rijlengtes, of er indexen bestaan, het RAM-geheugen op de server, enz.

De beste manier die ik kan bedenken om dit soort problemen aan te pakken (denkend aan onderhoudbaarheid en een brede benadering van efficiëntie) is door CTE's te gebruiken, waarmee je een tijdelijk resultaat kunt creëren en dat resultaat opnieuw kunt gebruiken in je query. CTE's gebruiken het trefwoord WITH, en in wezen een resultaat als een tabel, zodat u er meerdere keren mee kunt JOINEN:

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

De voordelen om het op deze manier te doen zijn:

  1. Elke CTE kan profiteren van een index op de juiste JOIN-predikaten en sneller resultaten retourneren voor precies die subset, in plaats van dat de uitvoeringsplanner probeert een reeks complexe predikaten op te lossen
  2. De CTE's kunnen afzonderlijk worden onderhouden, waardoor het oplossen van problemen met subsets eenvoudiger wordt
  3. Je schendt het DRY-principe niet
  4. Als de CTE waarde heeft buiten de query, kunt u deze naar een opgeslagen procedure verplaatsen en daar in plaats daarvan naar verwijzen


  1. IRI-software verbinden met Oracle

  2. Tabellen samenvoegen in Oracle SQL Developer

  3. MySQL-optimalisatie van enorme tafel

  4. SQL:Dynamische weergave met kolomnamen op basis van kolomwaarden in brontabel