¿Por qué no puedo utilizar alias de columna en la siguiente expresión SELECT?

Resuelto sergzach asked hace 8 años • 4 respuestas

¿Puedo modificar el siguiente para usar los alias de columna avg_timey cnten una expresión ROUND(avg_time * cnt, 2)?

SELECT 
    COALESCE(ROUND(stddev_samp(time), 2), 0) as stddev_time, 
    MAX(time) as max_time, 
    ROUND(AVG(time), 2) as avg_time, 
    MIN(time) as min_time, 
    COUNT(path) as cnt, 
    ROUND(avg_time * cnt, 2) as slowdown, path
FROM 
    loadtime
GROUP BY
    path
ORDER BY
    avg_time DESC
LIMIT 10;

Genera el siguiente error:

ERROR:  column "avg_time" does not exist
LINE 7:  ROUND(avg_time * cnt, 2) as slowdown, path

El siguiente, sin embargo, funciona bien (use expresiones primarias en lugar de alias de columna:

SELECT 
    COALESCE(ROUND(stddev_samp(time), 2), 0) as stddev_time, 
    MAX(time) as max_time, 
    ROUND(AVG(time), 2) as avg_time, 
    MIN(time) as min_time, 
    COUNT(path) as cnt, 
    ROUND(AVG(time) * COUNT(path), 2) as slowdown, path
FROM 
    loadtime
GROUP BY
    path
ORDER BY
    avg_time DESC
LIMIT 10;
sergzach avatar Jan 23 '16 04:01 sergzach
Aceptado

Puede utilizar un alias creado previamente en la declaración GROUP BYo HAVINGpero no en una declaración SELECTo WHERE. Esto se debe a que el programa procesa todos losSELECT declaraciones al mismo tiempo y aún no conoce el valor del alias.

La solución es encapsular la consulta en una subconsulta y luego el alias estará disponible afuera.

SELECT stddev_time, max_time, avg_time, min_time, cnt, 
       ROUND(avg_time * cnt, 2) as slowdown
FROM (
        SELECT 
            COALESCE(ROUND(stddev_samp(time), 2), 0) as stddev_time, 
            MAX(time) as max_time, 
            ROUND(AVG(time), 2) as avg_time, 
            MIN(time) as min_time, 
            COUNT(path) as cnt, 
            path
        FROM 
            loadtime
        GROUP BY
            path
        ORDER BY
            avg_time DESC
        LIMIT 10
   ) X;
Juan Carlos Oropeza avatar Jan 22 '2016 21:01 Juan Carlos Oropeza

El orden de ejecución de una consulta (y por tanto la evaluación de expresiones y alias) NO es el mismo que la forma en que está escrita. La posición "general" es que las cláusulas se evalúan en esta secuencia:

FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY

Por lo tanto, los alias de las columnas son desconocidos para la mayor parte de la consulta hasta que se completa la cláusula de selección (y es por eso que puede usar alias en la cláusula ORDER BY). Sin embargo los alias de tablas que se establecen en la cláusula from se entienden en las cláusulas donde ordenar por.

La solución más común es encapsular su consulta en una "tabla derivada".

Lectura sugerida: Orden de ejecución de la consulta SQL

Nota: diferentes bases de datos SQL tienen diferentes reglas específicas con respecto al uso de alias

EDITAR El propósito de recordar a los lectores la secuencia lógica de la cláusula es que a menudo ( pero no siempre ) los alias solo se vuelven referenciables DESPUÉS de la cláusula donde se declara el alias. El más común es que SELECTla cláusula pueda utilizar los alias declarados en la ORDER BYcláusula. En particular, SELECTno se puede hacer referencia a un alias declarado en una cláusula dentro de la misma SELECTcláusula.

Pero tenga en cuenta que, debido a diferencias en los productos, no todos los dbms se comportarán de esta manera.

Adrian Maxwell avatar Jan 22 '2016 21:01 Adrian Maxwell