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

PostgreSQL:Die Verwendung der AND-Anweisung in LEFT JOIN funktioniert nicht wie erwartet

Die Verwirrung um LEFT JOIN und WHERE Klausel wurde mehrfach verdeutlicht:

Diese interessante Frage bleibt:

Es gibt keine expliziten Abfragehinweise in Postgres. (Dies ist eine Frage der laufenden Debatte.) Aber es gibt immer noch verschiedene Tricks, um Postgres dazu zu bringen, sich Ihren Weg zu bahnen.

Aber fragen Sie sich zuerst: Warum hat der Abfrageplaner den ausgewählten Plan von vornherein als günstiger eingeschätzt? Ist Ihre Serverkonfiguration grundsätzlich in Ordnung? Kosteneinstellungen ausreichend? autovacuum laufend? Postgres-Version veraltet? Umgehen Sie ein zugrunde liegendes Problem, das wirklich behoben werden sollte?

Wenn Sie Postgres zwingen, es auf Ihre Weise zu tun, sollten Sie sicher sein, dass es nach einem Versions-Upgrade oder Update der Serverkonfiguration nicht zurückfeuert ... Sie sollten besser wissen, was Sie genau tun.

Das heißt, Sie können zwingen Sie Postgres dazu, "einige Datensätze herauszufiltern, bevor Sie JOIN ausführen " mit einer Unterabfrage, in der Sie OFFSET 0 hinzufügen - was logischerweise nur Rauschen ist, aber Postgres daran hindert, es in Form eines regulären Joins neu anzuordnen. (Immerhin Abfragehinweis)

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;

Oder Sie können einen CTE verwenden (weniger obskur, aber teurer). Oder andere Tricks wie das Setzen bestimmter Konfigurationsparameter. Oder in diesem speziellen Fall würde ich einen LATERAL verwenden Join mit dem gleichen Effekt:

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;

Verwandte:

Hier ist ein ausführlicher Blog zu Abfragehinweisen von 2ndQuadrant. Fünf Jahre alt, aber noch gültig.