sql >> Database >  >> RDS >> PostgreSQL

Waarom kan ik afhankelijke kolommen niet uitsluiten van `GROUP BY` als ik aggregeer met een sleutel?

Omdat alleen de PK alle kolommen van een onderliggende tabel dekt in de GROUP BY clausule. Daarom werkt je eerste query. Een UNIQUE beperking niet.

De combinatie van een niet-uitstelbaar UNIQUE en een NOT NULL beperking zou ook in aanmerking komen. Maar dat is niet geïmplementeerd - evenals enkele andere functionele afhankelijkheden die bekend zijn bij de SQL-standaard. Peter Eisentraut, de hoofdauteur van de functie, had meer in gedachten, maar er werd destijds vastgesteld dat de vraag laag is en de bijbehorende kosten hoog kunnen zijn. Zie de discussie over de functie op pgsql-hackers.

De handleiding:

Wanneer GROUP BY aanwezig is, of er zijn geaggregeerde functies aanwezig, het is niet geldig voor de SELECT lijstexpressies om naar niet-gegroepeerde kolommen te verwijzen, behalve binnen geaggregeerde functies of wanneer de niet-gegroepeerde kolom functioneel afhankelijk is van de gegroepeerde kolommen, aangezien er anders meer dan één mogelijke waarde zou zijn om te retourneren voor een niet-gegroepeerde kolom. Er is sprake van een functionele afhankelijkheid als de gegroepeerde kolommen (of een subset daarvan) de primaire sleutel zijn van de tabel die de niet-gegroepeerde kolom bevat.

En meer expliciet:

PostgreSQL herkent functionele afhankelijkheid (waardoor kolommen kunnen worden weggelaten uit GROUP BY ) alleen als de primaire sleutel van een tabel is opgenomen in de GROUP BY lijst. De SQL-standaard specificeert aanvullende voorwaarden die moeten worden herkend.

Sinds c.vin is UNIQUE NOT NULL , kunt u uw tweede zoekopdracht oplossen door in plaats daarvan de PK-kolom te gebruiken:

...
group by c.id;

Afgezien daarvan, terwijl referentiële integriteit wordt afgedwongen en de hele tabel wordt opgevraagd, kunnen beide gegeven zoekopdrachten aanzienlijk goedkoper zijn:verzamel rijen in appraisal voor de toetreden. Dit elimineert de noodzaak om GROUP BY in de buitenste SELECT a priori. Vind ik leuk:

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;

Zie:

  • Meerdere array_agg()-aanroepen in één query

Gerelateerd:

  • SQL-statement werkt in MySQL werkt niet in Postgresql - Sum &group_by rails 3
  • PostgreSQL - GROUP BY-clausule



  1. Android:SQLite bespaart stringarray?

  2. Een PostgreSQL-array toewijzen met Hibernate

  3. Krijg een lijst met tabellen met of zonder primaire sleutelbeperking in alle databases van SQL Server-instantie - SQL Server / TSQL-zelfstudie, deel 61

  4. ALTER TABLE in MySQL:vriend of vijand?