sql >> Base de Datos >  >> RDS >> PostgreSQL

GRUPO o DISTINTO después de JOIN devuelve duplicados

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 de meta , 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 pocos product_id distintos ).
    Esta es la única forma que conozco de usar un índice para una consulta DISTINCT en toda la tabla.