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

Perché non posso escludere le colonne dipendenti da "GRUPPO PER" quando aggrego in base a una chiave?

Perché solo il PK copre tutte le colonne di una tabella sottostante in GROUP BY clausola. Quindi la tua prima query funziona. Un UNIQUE vincolo no.

La combinazione di un UNIQUE non differibile e un NOT NULL anche il vincolo si qualificherebbe. Ma questo non è implementato, così come alcune altre dipendenze funzionali note allo standard SQL. Peter Eisentraut, l'autore principale del film, aveva in mente di più, ma all'epoca era determinato che la domanda fosse bassa e che i costi associati potessero essere elevati. Vedi la discussione sulla funzione su pgsql-hacker.

Il manuale:

Quando GROUP BY è presente, o sono presenti funzioni aggregate, non è valido per SELECT list le espressioni per fare riferimento a colonne non raggruppate tranne all'interno di funzioni aggregate o quando la colonna non raggruppata dipende funzionalmente dalle colonne raggruppate, poiché altrimenti ci sarebbe più di un valore possibile da restituire per una colonna non raggruppata. Esiste una dipendenza funzionale se le colonne raggruppate (o un loro sottoinsieme) sono la chiave primaria della tabella contenente la colonna non raggruppata.

E più esplicitamente:

PostgreSQL riconosce la dipendenza funzionale (consentendo che le colonne siano omesse da GROUP BY ) solo quando la chiave primaria di una tabella è inclusa nel GROUP BY elenco. Lo standard SQL specifica condizioni aggiuntive che devono essere riconosciute.

Da c.vin è UNIQUE NOT NULL , puoi correggere la tua seconda query utilizzando invece la colonna PK:

...
group by c.id;

A parte, mentre viene applicata l'integrità referenziale e viene interrogata l'intera tabella, entrambe le query fornite possono essere sostanzialmente più economiche:righe aggregate in appraisal prima l'unione. Questo elimina la necessità di GROUP BY nel SELECT esterno a priori. Come:

SELECT c.vin, c.color, c.brand
     , a.min_appraisal
     , a.max_appraisal
FROM   car c
LEFT   JOIN (
   SELECT car_vin
        , min(price) AS min_appraisal
        , max(price) AS max_appraisal
   FROM   appraisal
   GROUP  BY car_vin
   ) a ON a.car_vin = c.vin;

Vedi:

  • Più chiamate array_agg() in una singola query

Correlati:

  • Istruzione SQL funzionante in MySQL non funzionante in Postgresql - Sum &group_by rails 3
  • PostgreSQL - clausola GROUP BY