Beim Abrufen aller oder der meisten Zeilen aus einer Tabelle besteht der schnellste Weg für diese Art von Abfrage normalerweise darin, zuerst zu aggregieren / zu disambiguieren und trete später bei :
SELECT *
FROM products p
JOIN (
SELECT DISTINCT ON (product_id) *
FROM meta
ORDER BY product_id, id DESC
) m ON m.product_id = p.id;
Je mehr Zeilen in meta
pro Zeile in products
, desto größer ist die Auswirkung auf die Leistung.
Natürlich möchten Sie einen ORDER BY
hinzufügen -Klausel in der Unterabfrage definieren welche Zeile, die aus jedem Satz in der Unterabfrage auszuwählen ist. @Craig und @Clodoaldo haben dir bereits davon erzählt. Ich gebe das meta
zurück Zeile mit der höchsten id
.
SQL-Geige.
Details für DISTINCT ON
:
- Erste Zeile in jeder GROUP BY-Gruppe auswählen?
Leistung optimieren
Allerdings ist dies nicht immer die schnellste Lösung. Je nach Datenverteilung gibt es verschiedene andere Abfragestile. Für diesen einfachen Fall mit einem anderen Join lief dieser in einem Test mit großen Tabellen erheblich schneller:
SELECT p.*, sub.meta_id, m.product_id, m.price, m.flag
FROM (
SELECT product_id, max(id) AS meta_id
FROM meta
GROUP BY 1
) sub
JOIN meta m ON m.id = sub.meta_id
JOIN products p ON p.id = sub.product_id;
Wenn Sie nicht die nicht beschreibende id
verwenden würden als Spaltennamen würden wir nicht auf Namenskollisionen stoßen und könnten einfach SELECT p.*, m.*
schreiben . (Ich nie Verwenden Sie id
als Spaltenname.)
Wenn Leistung Ihre höchste Anforderung ist, ziehen Sie weitere Optionen in Betracht:
- eine
MATERIALIZED VIEW
mit voraggregierten Daten ausmeta
, wenn sich Ihre Daten nicht (viel) ändern. - ein rekursiver CTE, der einen losen Index-Scan emuliert für ein großes
meta
Tabelle mit vielen Zeilen pro Produkt (relativ wenige eindeutigeproduct_id
).
Dies ist die einzige Möglichkeit, die ich kenne, um einen Index für eine DISTINCT-Abfrage über die gesamte Tabelle zu verwenden.