Докато се извличат всички или повечето редове от таблица, най-бързият начин за този тип заявка обикновено е да се обобщи/определи първото и се присъединете по-късно :
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;
Колкото повече редове в meta на ред в products , толкова по-голямо е влиянието върху производителността.
Разбира се, ще искате да добавите ORDER BY клаузата в подзаявката дефинира коя ред, за да изберете от всеки набор в подзаявката. @Craig и @Clodoaldo вече ви казаха за това. Връщам meta ред с най-висок id .
SQL Fiddle.
Подробности за DISTINCT ON :
- Изберете ли първия ред във всяка група GROUP BY?
Оптимизиране на производителността
Все пак това не винаги е най-бързото решение. В зависимост от разпределението на данните има различни други стилове на заявки. За този прост случай, включващ друго присъединяване, този работи значително по-бързо в тест с големи таблици:
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;
Ако не бихте използвали неописателния id като имена на колони, няма да се сблъскаме с колизии на именуване и бихме могли просто да напишем SELECT p.*, m.* . (Аз никога използвайте id като име на колона.)
Ако производителността е вашето първостепенно изискване, помислете за повече опции:
- a
MATERIALIZED VIEWс предварително обобщени данни отmeta, ако данните ви не се променят (много). - рекурсивен CTE, емулиращо разхлабено сканиране на индекс за голям
metaтаблица с много редове на продукт (сравнително малко различниproduct_id).
Това е единственият начин, който знам да използвам индекс за DISTINCT заявка върху цялата таблица.