Podczas pobierania wszystkich lub większości wierszy z tabeli najszybszym sposobem dla tego typu zapytań jest zazwyczaj agregacja/ujednoznacznienie pierwszy i dołącz później :
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;
Więcej wierszy w meta na wiersz w products , tym większy wpływ na wydajność.
Oczywiście będziesz chciał dodać ORDER BY klauzula w podzapytaniu definiuje które wiersz do wybrania z każdego zestawu w podzapytaniu. @Craig i @Clodoaldo już ci o tym powiedzieli. Zwracam meta wiersz z najwyższym id .
Skrzypce SQL.
Szczegóły dla DISTINCT ON :
- Wybrać pierwszy wiersz w każdej grupie GROUP BY?
Optymalizuj wydajność
Jednak nie zawsze jest to najszybsze rozwiązanie. W zależności od dystrybucji danych istnieją różne inne style zapytań. W tym prostym przypadku z innym złączeniem, ten przebiegł znacznie szybciej w teście z dużymi tabelami:
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;
Jeśli nie użyjesz nieopisowego id jako nazwy kolumn, nie napotkalibyśmy kolizji nazw i moglibyśmy po prostu napisać SELECT p.*, m.* . (Ja nigdy użyj id jako nazwę kolumny.)
Jeśli wydajność jest Twoim najważniejszym wymaganiem, rozważ więcej opcji:
MATERIALIZED VIEWze wstępnie zagregowanymi danymi zmeta, jeśli Twoje dane się nie zmieniają (znacznie).- rekurencyjne CTE emulujące luźne skanowanie indeksu dla dużego
metastół z wieloma wierszy na produkt (stosunkowo kilka odrębnychproduct_id).
To jedyny znany mi sposób na użycie indeksu dla zapytania DISTINCT dla całej tabeli.