Articles

MySQL :: Manual de referencia de MySQL 5.6 :: 12.19.3 Manejo MySQL del GRUPO POR

12.19.3 Manejo MySQL del GRUPO POR

En SQL estándar, una consulta que incluye una cláusula GROUP BY no puede hacer referencia a columnas no agregadas en la lista de selección que no se nombran en la cláusula GROUP BY. Por ejemplo, esta consulta es ilegal en SQL estándar porque la columna no agregada name de la lista de selección no aparece en GROUP BY:

SELECT o.custid, c.name, MAX(o.payment) FROM orders AS o, customers AS c WHERE o.custid = c.custid GROUP BY o.custid;

Para que la consulta sea legal, el name columna debe ser omitido de la lista de selección o nombrado en el GROUP BY cláusula.

MySQL amplía el uso SQL estándar de GROUP BY para que la lista de selección pueda hacer referencia a columnas no agregadas sin nombre en la cláusula GROUP BY. Esto significa que la consulta anterior es legal en MySQL. Puede usar esta función para obtener un mejor rendimiento al evitar la clasificación y agrupación de columnas innecesarias. Sin embargo, esto es útil principalmente cuando todos los valores de cada columna no agregada no nombrada en GROUP BY son los mismos para cada grupo. El servidor es libre de elegir cualquier valor de cada grupo, por lo que, a menos que sean los mismos, los valores elegidos no son deterministas. Además, no se puede influir en la selección de valores de cada grupo añadiendo una cláusula ORDER BY. La ordenación del conjunto de resultados se produce después de que se hayan elegido los valores, y ORDER BY no afecta a los valores de cada grupo que elija el servidor.

Una extensión MySQL similar se aplica a la cláusula HAVING. En SQL estándar, una consulta no puede hacer referencia a columnas no agregadas de la cláusula HAVING que no tengan nombre en la cláusula GROUP BY. Para simplificar los cálculos, una extensión MySQL permite referencias a dichas columnas. Esta extensión asume que las columnas no agrupadas tienen los mismos valores de grupo. De lo contrario, el resultado es no determinista.

Para deshabilitar la extensión MySQL GROUP BY y habilitar el comportamiento SQL estándar, habilite el modo SQL ONLY_FULL_GROUP_BY. En este caso, las columnas no nombradas en la cláusula GROUP BY no se pueden usar en la lista de selección o en la cláusula HAVING a menos que estén encerradas en una función agregada.

La extensión de lista de selección también se aplica a ORDER BY. Es decir, puede hacer referencia a columnas no agregadas en la cláusula ORDER BY que no aparecen en la cláusula GROUP BY. (Sin embargo, como se mencionó anteriormente, ORDER BY no afecta qué valores se eligen de columnas no agregadas; solo los ordena después de que se han elegido.) Esta extensión no se aplica si el modo SQL ONLY_FULL_GROUP_BY está habilitado.

Si una consulta tiene funciones agregadas y no tiene la cláusula GROUP BY, no puede tener columnas no agregadas en la lista de selección, HAVING condición, o ORDER BY lista con ONLY_FULL_GROUP_BY habilitado:

mysql> SELECT name, MAX(age) FROM t;ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...)with no GROUP columns is illegal if there is no GROUP BY clause

Sin GROUP BY, hay un solo grupo y no es determinista que name valor a elegir por el grupo.

Otra extensión MySQL para SQL estándar permite referencias en la cláusula HAVING a expresiones con alias en la lista de selección. Habilitar ONLY_FULL_GROUP_BY evita esto. Por ejemplo, la siguiente consulta devuelve name valores que solo aparecen una vez en la tabla orders; la consulta es aceptada, independientemente de si ONLY_FULL_GROUP_BY está habilitado:

SELECT name, COUNT(name) FROM orders GROUP BY name HAVING COUNT(name) = 1;

La siguiente consulta es aceptada sólo si ONLY_FULL_GROUP_BY está deshabilitada.

SELECT name, COUNT(name) AS c FROM orders GROUP BY name HAVING c = 1;

Si está intentando seguir SQL estándar, solo puede usar expresiones de columna en las cláusulas GROUP BY. Como solución alternativa, use un alias para la expresión:

SELECT id, FLOOR(value/100) AS val FROM tbl_name GROUP BY id, val;

MySQL permite expresiones sin columnas en cláusulas GROUP BY, por lo que el alias es innecesario:

SELECT id, FLOOR(value/100) FROM tbl_name GROUP BY id, FLOOR(value/100);