Error de PostgreSQL: 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...
^
En una consulta agrupada, cada columna seleccionada debe ser o parte de la clave de agrupación o estar envuelta en un agregado — de lo contrario hay muchos valores candidatos por grupo y ninguna regla para elegir uno. Las bases de datos que "servicialmente" eligen uno de todos modos (como hacía el MySQL antiguo) devuelven datos no deterministas; PostgreSQL se niega.
Qué significa este error
Cada fila de resultado de una consulta GROUP BY representa muchas filas de origen. department está bien (define el grupo), count(*) está bien (agrega el grupo) — pero ¿name? ¿Cuál de los 40 empleados del departamento debería aportarlo? La consulta es genuinamente ambigua, y el error es la respuesta del estándar SQL.
Una excepción documentada: agrupa por la clave primaria de una tabla, y puedes seleccionar cualquier columna de esa tabla — son funcionalmente dependientes de la clave, así que no hay ambigüedad. GROUP BY u.id permite legítimamente SELECT u.name, u.email, ....
Causas comunes
- Añadir una columna al SELECT de una consulta agrupada existente sin pensar qué valor de grupo debería llevar.
- Portar consultas desde MySQL, donde esto históricamente "funcionaba".
- Querer algo que GROUP BY no expresa: "la última fila / la fila superior por grupo" — una forma de consulta completamente distinta (abajo).
Cómo diagnosticarlo
Para la columna señalada, responde una pregunta: ¿el valor de qué fila quiero realmente? "Cualquiera, son todos iguales" → agrupa por la clave que lo hace así (o la PK). "El máx/mín/suma" → agrega. "El de la fila más reciente" → quieres DISTINCT ON, no GROUP BY.
Cómo solucionarlo
-- El valor está determinado por el grupo → agrupa por la clave:
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 está permitido
-- Quieres un agregado de él:
SELECT department, count(*), max(salary) FROM employees GROUP BY department;
-- Quieres "la fila más reciente por grupo" → DISTINCT ON:
SELECT DISTINCT ON (customer_id) *
FROM orders
ORDER BY customer_id, created_at DESC;
PostgreSQL 16 también añade any_value() para el caso genuino de "cualquiera vale".
