sql >> Databáze >  >> RDS >> PostgreSQL

Jak jednoduše a efektivně dotazovat na vnořené vztahy v SQL?

Jako u každého dotazu je nejúčinnější metodou „závisí“. Ve hře je mnoho proměnných – počet řádků v tabulkách, délka řádků, zda existují indexy, RAM na serveru atd.

Nejlepší způsob, jak se vypořádat s tímto druhem problému (s ohledem na udržovatelnost a braod přístup k efektivitě), je použití CTE, které vám umožní vytvořit dočasný výsledek a znovu použít tento výsledek v celém dotazu. CTE používají klíčové slovo WITH a v podstatě jako výsledek jako tabulku, takže se proti němu můžete vícekrát PŘIPOJIT:

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

Výhody tohoto způsobu jsou:

  1. Každý CTE může využít index na příslušných predikátech JOIN a rychleji vrátit výsledky právě pro tuto podmnožinu, místo aby se plánovač provádění pokoušel vyřešit řadu složitých predikátů
  2. CTE lze udržovat individuálně, což usnadňuje odstraňování problémů s podmnožinami
  3. Neporušujete zásadu DRY
  4. Pokud má CTE hodnotu mimo dotaz, můžete jej přesunout do uložené procedury a místo toho na ni odkazovat


  1. Obrácení efektu `mysqli_real_escape_string`

  2. Funkce MAX v klauzuli where mysql

  3. Jak zobrazit aktuální nastavení pro nulový výstup v PostgreSQL (psql)

  4. Nejrychlejší dotaz pro kontrolu existence řádku v Oracle?