PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

GROUP ou DISTINCT após JOIN retorna duplicatas


Ao recuperar todas ou a maioria das linhas de uma tabela, a maneira mais rápida para esse tipo de consulta normalmente é agregar/desambiguar primeiro e participe mais 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;

Quanto mais linhas em meta por linha em products , maior o impacto no desempenho.

Claro, você vai querer adicionar um ORDER BY cláusula na subconsulta define qual linha para escolher cada conjunto na subconsulta. @Craig e @Clodoaldo já te falaram sobre isso. Estou retornando o meta linha com o id mais alto .

violino SQL.

Detalhes para DISTINCT ON :
  • Selecionar a primeira linha em cada grupo GROUP BY?

Otimize o desempenho


Ainda assim, esta nem sempre é a solução mais rápida. Dependendo da distribuição de dados, existem vários outros estilos de consulta. Para este caso simples envolvendo outra junção, esta correu consideravelmente mais rápido em um teste com grandes tabelas:
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;

Se você não usar o id não descritivo como nomes de colunas, não teríamos colisões de nomenclatura e poderíamos simplesmente escrever SELECT p.*, m.* . (Eu nunca use id como nome da coluna.)

Se o desempenho for seu requisito primordial, considere mais opções:
  • uma MATERIALIZED VIEW com dados pré-agregados de meta , se seus dados não mudarem (muito).
  • um CTE recursivo emulando uma varredura de índice solto para um grande meta tabela com muitos linhas por produto (relativamente poucos product_id distintos ).
    Esta é a única maneira que conheço de usar um índice para uma consulta DISTINCT em toda a tabela.