sql >> Database teknologi >  >> RDS >> PostgreSQL

GROUP eller DISTINCT efter JOIN returnerer dubletter

Mens du henter alle eller de fleste rækker fra en tabel, er den hurtigste måde for denne type forespørgsel typisk at aggregere / disambiguere først og deltag senere :

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;

Jo flere rækker i meta række i products , jo større indvirkning på ydeevnen.

Selvfølgelig skal du tilføje en ORDER BY klausul i underforespørgslen definerer hvilken række for at vælge fra hvert sæt i underforespørgslen. @Craig og @Clodoaldo har allerede fortalt dig om det. Jeg returnerer meta række med det højeste id .

SQL Fiddle.

Detaljer for DISTINCT ON :

  • Vælg første række i hver GROUP BY-gruppe?

Optimer ydeevnen

Alligevel er dette ikke altid den hurtigste løsning. Afhængigt af datadistribution er der forskellige andre forespørgselsstile. For denne simple sag, der involverede en anden join, kørte denne betydeligt hurtigere i en test med store borde:

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;

Hvis du ikke ville bruge det ikke-beskrivende id som kolonnenavne ville vi ikke støde på navnekollisioner og kunne simpelthen skrive SELECT p.*, m.* . (Jeg aldrig brug id som kolonnenavn.)

Hvis ydeevne er dit vigtigste krav, så overvej flere muligheder:

  • en MATERIALIZED VIEW med forudaggregerede data fra meta , hvis dine data ikke ændrer sig (meget).
  • en rekursiv CTE, der emulerer en løs indeksscanning for en stor meta tabel med mange rækker pr. produkt (relativt få distinkte product_id). ).
    Dette er den eneste måde, jeg kender til at bruge et indeks til en DISTINCT-forespørgsel over hele tabellen.


  1. SQL:Få oprettet registreringer i tidsinterval for bestemte datoer

  2. Kan jeg skrive PostgreSQL-funktioner på Ruby on Rails?

  3. Kan ikke returnere resultater fra lagret procedure ved hjælp af Python-markøren

  4. Ydeevne overraskelser og antagelser:DATEADD