PostgreSQL-Fehler: column must appear in the GROUP BY clause
ERROR: column "employees.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT department, name, count(*) FROM employees GROUP BY d...
^
In einer gruppierten Query muss jede selektierte Spalte entweder Teil des Gruppenschlüssels oder in ein Aggregat eingehüllt sein — andernfalls gibt es viele Kandidatenwerte pro Gruppe und keine Regel, um einen auszuwählen. Datenbanken, die "hilfsbereit" trotzdem einen auswählen (wie es ältere MySQL tat), liefern nichtdeterministische Daten; PostgreSQL verweigert.
Was dieser Fehler bedeutet
Jede Ergebniszeile einer GROUP BY-Query repräsentiert viele Quellzeilen. department ist in Ordnung (es definiert die Gruppe), count(*) ist in Ordnung (es aggregiert die Gruppe) — aber name? Welcher der 40 Mitarbeiter der Abteilung soll ihn liefern? Die Query ist wirklich mehrdeutig, und der Fehler ist die Antwort des SQL-Standards.
Eine dokumentierte Ausnahme: gruppieren Sie nach dem Primärschlüssel einer Tabelle, und Sie dürfen jede Spalte dieser Tabelle selektieren — sie sind funktional vom Schlüssel abhängig, es gibt also keine Mehrdeutigkeit. GROUP BY u.id erlaubt legitim SELECT u.name, u.email, ....
Häufige Ursachen
- Eine Spalte zum SELECT einer bestehenden gruppierten Query hinzufügen, ohne darüber nachzudenken, welchen Gruppenwert sie tragen soll.
- Queries aus MySQL portieren, wo dies historisch "funktionierte".
- Etwas wollen, das GROUP BY nicht ausdrückt: "die neueste / oberste Zeile pro Gruppe" — eine völlig andere Query-Form (unten).
So diagnostizieren Sie ihn
Beantworten Sie für die markierte Spalte eine Frage: welchen Zeilenwert will ich eigentlich? "Egal, sie sind alle gleich" → gruppieren Sie nach dem Schlüssel, der das so macht (oder dem PK). "Das Max/Min/Summe" → aggregieren. "Der aus der neuesten Zeile" → Sie wollen DISTINCT ON, nicht GROUP BY.
So beheben Sie ihn
-- Der Wert wird durch die Gruppe bestimmt → nach dem Schlüssel gruppieren:
SELECT u.id, u.name, count(o.id)
FROM users u JOIN orders o ON o.user_id = u.id
GROUP BY u.id; -- PK: u.name ist erlaubt
-- Sie wollen ein Aggregat davon:
SELECT department, count(*), max(salary) FROM employees GROUP BY department;
-- Sie wollen "die neueste Zeile pro Gruppe" → DISTINCT ON:
SELECT DISTINCT ON (customer_id) *
FROM orders
ORDER BY customer_id, created_at DESC;
PostgreSQL 16 fügt außerdem any_value() für den echten "irgendeine tut's"-Fall hinzu.
