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 deSELECT
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 deGROUP 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