Al recuperar todas o la mayoría de las filas de una tabla, la forma más rápida para este tipo de consulta suele ser agregar/desambiguar primero y unirse más tarde :
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;
Cuantas más filas en meta
por fila en products
, mayor será el impacto en el rendimiento.
Por supuesto, querrá agregar un ORDER BY
cláusula en la subconsulta define cuál fila para seleccionar cada conjunto en la subconsulta. @Craig y @Clodoaldo ya te hablaron de eso. Estoy devolviendo el meta
fila con el id
más alto .
Violín SQL.
Detalles para DISTINCT ON
:
- ¿Seleccionar la primera fila en cada grupo GROUP BY?
Optimizar el rendimiento
Aún así, esta no es siempre la solución más rápida. Dependiendo de la distribución de datos, existen otros estilos de consulta. Para este caso simple que involucra otra unión, esta funcionó considerablemente más rápido en una prueba con tablas grandes:
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;
Si no usaría el id
no descriptivo como nombres de columna, no nos encontraríamos con colisiones de nombres y simplemente podríamos escribir SELECT p.*, m.*
. (Yo nunca usar id
como nombre de columna.)
Si el rendimiento es su requisito primordial, considere más opciones:
- una
MATERIALIZED VIEW
con datos agregados previamente demeta
, si sus datos no cambian (mucho). - un CTE recursivo que emula un escaneo de índice suelto para un grande
meta
mesa con muchos filas por producto (relativamente pocosproduct_id
distintos ).
Esta es la única forma que conozco de usar un índice para una consulta DISTINCT en toda la tabla.