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

PostgreSQL:Použití příkazu AND v LEFT JOIN nefunguje podle očekávání

Zmatek kolem LEFT JOIN a WHERE klauzule byla mnohokrát objasněna:

Tato zajímavá otázka zůstává:

V Postgresu nejsou žádné explicitní tipy na dotazy. (Což je předmětem pokračujících debat.) Stále však existují různé triky, jak přimět Postgres, aby vám zahnul.

Nejdřív se však zeptejte sami sebe: Proč plánovač dotazů odhadl, že vybraný plán je pro začátek levnější? Je konfigurace vašeho serveru v zásadě rozumná? Je nastavení ceny dostatečné? autovacuum běh? Verze Postgresu je zastaralá? Řešíte základní problém, který by měl být skutečně vyřešen?

Pokud přinutíte Postgres, aby to udělal po svém, měli byste si být jisti, že se po aktualizaci verze nebo aktualizaci konfigurace serveru znovu nespustí... Raději byste měli vědět, co přesně děláte.

To znamená, že můžete donutit Postgres, aby "odfiltroval některé záznamy před provedením JOIN " s poddotazem, kam přidáte OFFSET 0 - což je logicky jen šum, ale brání Postgresu v jeho přeskupení do podoby běžného spojení. (Koneckonců nápověda k dotazu)

SELECT la.listing_id, la.id, lar.*
FROM  (
   SELECT listing_id, id
   FROM   la
   WHERE  listing_id = 2780
   OFFSET 0
   ) la
LEFT   JOIN lar  ON lar.application_id = la.id;

Nebo můžete použít CTE (méně obskurní, ale dražší). Nebo jiné triky, jako je nastavení určitých konfiguračních parametrů. Nebo v tomto konkrétním případě použil bych LATERAL spojit se stejným efektem:

SELECT la.listing_id, la.id, lar.*
FROM   la
LEFT  JOIN LATERAL (
   SELECT *
   FROM   lar
   WHERE  application_id = la.id
   )  lar ON true
WHERE  la.listing_id = 2780;

Související:

Zde je rozsáhlý blog o nápovědách k dotazům od 2ndQuadrant. Pět let staré, ale stále platné.



  1. Jak vložit informace do sloupců pro e-mail

  2. Porovnání řetězce dotazu SELECT v MySQL

  3. Získejte jednu položku z řetězce seznamu v MySQL

  4. Opakujte řetězec vícekrát v MySQL – REPEAT()