sql >> Databáze >  >> RDS >> PostgreSQL

GROUP nebo DISTINCT po JOIN vrátí duplikáty

Při načítání všech nebo většiny řádků z tabulky je nejrychlejším způsobem pro tento typ dotazu obvykle nejprve agregovat / rozčlenit a připojte se později :

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;

Čím více řádků v meta na řádek v products , tím větší bude dopad na výkon.

Samozřejmě budete chtít přidat ORDER BY klauzule v poddotazu definujte který řádek pro výběr z každé sady v poddotazu. @Craig a @Clodoaldo vám o tom již řekli. Vracím meta řádek s nejvyšším id .

SQL Fiddle.

Podrobnosti pro DISTINCT ON :

  • Vybrat první řádek v každé skupině GROUP BY?

Optimalizace výkonu

Přesto to není vždy nejrychlejší řešení. V závislosti na distribuci dat existují různé další styly dotazů. V tomto jednoduchém případě zahrnujícím další spojení tento běžel podstatně rychleji v testu s velkými stoly:

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;

Pokud byste nepoužili nepopisné id jako názvy sloupců bychom nenarazili na kolize pojmenování a mohli bychom jednoduše napsat SELECT p.*, m.* . (Já nikdy použijte id jako název sloupce.)

Pokud je vaším prvořadým požadavkem výkon, zvažte další možnosti:

  • a MATERIALIZED VIEW s předem agregovanými daty z meta , pokud se vaše data nezmění (příliš).
  • rekurzivní CTE emulující volné skenování indexu na velké meta tabulka s mnoha řádků na produkt (relativně málo odlišných product_id ).
    Toto je jediný způsob, jak znám použít index pro DISTINCT dotaz na celou tabulku.


  1. Jak nastavit a přihlásit se jako uživatel root v MySQL

  2. Řešení problémů generátoru číselných řad – 2. část

  3. Jak změnit sloupec z NULL na NOT NULL

  4. Lomítko nebo žádné lomítko?