sql >> Database >  >> RDS >> PostgreSQL

GROUP of DISTINCT na JOIN retourneert duplicaten

Bij het ophalen van alle of de meeste rijen uit een tabel, is de snelste manier voor dit type zoekopdracht meestal om eerst te aggregeren / ondubbelzinnig maken. en doe later mee :

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;

Hoe meer rijen in meta per rij in products , hoe groter de impact op de prestaties.

Natuurlijk wil je een ORDER BY . toevoegen clausule in de subquery definiëren welke rij om uit elke set in de subquery te kiezen. @Craig en @Clodoaldo hebben je daar al over verteld. Ik retourneer de meta rij met de hoogste id .

SQL Fiddle.

Details voor DISTINCT ON :

  • Selecteer de eerste rij in elke GROUP BY-groep?

Prestaties optimaliseren

Toch is dit niet altijd de snelste oplossing. Afhankelijk van de gegevensdistributie zijn er verschillende andere zoekstijlen. Voor dit simpele geval met een andere join, liep deze aanzienlijk sneller in een test met grote tafels:

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;

Als u de niet-beschrijvende id . niet zou gebruiken als kolomnamen zouden we geen naamconflicten tegenkomen en konden we gewoon SELECT p.*, m.* schrijven . (Ik nooit gebruik id als kolomnaam.)

Als prestaties uw belangrijkste vereiste zijn, overweeg dan meer opties:

  • een MATERIALIZED VIEW met vooraf geaggregeerde gegevens van meta , als uw gegevens niet (veel) veranderen.
  • een recursieve CTE die een losse index-scan emuleert voor een grote meta tafel met veel rijen per product (relatief weinig verschillende product_id ).
    Dit is de enige manier die ik ken om een ​​index te gebruiken voor een DISTINCT-query over de hele tabel.


  1. Migreren van Maxscale naar de ProxySQL Load Balancer

  2. Hoe MySQL op Ubuntu te installeren

  3. Boomitem vullen met recordgroep in Oracle-formulieren

  4. Oracle Bulk Collect Voorbeeld met Cursor Rowtype Type Object