Denn nur der PK deckt alle Spalten einer zugrunde liegenden Tabelle im GROUP BY
ab Klausel. Daher funktioniert Ihre erste Abfrage. Ein UNIQUE
Einschränkung nicht.
Die Kombination eines nicht aufschiebbaren UNIQUE
und ein NOT NULL
Einschränkung würde auch qualifizieren. Aber das ist nicht implementiert - ebenso wie einige andere funktionale Abhängigkeiten, die dem SQL-Standard bekannt sind. Peter Eisentraut, der Hauptautor des Features, hatte mehr im Sinn, aber es wurde damals festgestellt, dass die Nachfrage gering und die damit verbundenen Kosten hoch sein könnten. Siehe die Diskussion über das Feature auf pgsql-hackers.
Das Handbuch:
Wenn GROUP BY
vorhanden ist oder Aggregatfunktionen vorhanden sind, ist es für SELECT
nicht gültig Listenausdrücke auf nicht gruppierte Spalten verweisen, außer innerhalb von Aggregatfunktionen oder wenn die nicht gruppierte Spalte funktional von den gruppierten Spalten abhängig ist, da es sonst mehr als einen möglichen Wert geben würde, der für eine nicht gruppierte Spalte zurückgegeben werden könnte. Eine funktionale Abhängigkeit besteht, wenn die gruppierten Spalten (oder eine Teilmenge davon) der Primärschlüssel der Tabelle sind, die die nicht gruppierte Spalte enthält.
Und noch expliziter:
PostgreSQL erkennt funktionale Abhängigkeiten (wodurch Spalten aus GROUP BY
weggelassen werden können ) nur, wenn der Primärschlüssel einer Tabelle im GROUP BY
enthalten ist aufführen. Der SQL-Standard spezifiziert zusätzliche Bedingungen, die erkannt werden sollten.
Seit c.vin
ist UNIQUE NOT NULL
, können Sie Ihre zweite Abfrage korrigieren, indem Sie stattdessen die PK-Spalte verwenden:
...
group by c.id;
Abgesehen davon, während die referenzielle Integrität erzwungen und die gesamte Tabelle abgefragt wird, können beide angegebenen Abfragen wesentlich billiger sein:aggregierte Zeilen in appraisal
vorher der Beitritt. Dadurch entfällt die Notwendigkeit von GROUP BY
im äußeren SELECT
a priori. Wie:
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;
Siehe:
- Mehrere array_agg()-Aufrufe in einer einzigen Abfrage
Verwandte:
- SQL-Anweisung, die in MySQL funktioniert, funktioniert nicht in Postgresql - Sum &group_by rails 3
- PostgreSQL - GROUP BY-Klausel