为什么不能在下一个SELECT表达式中使用列别名?

ser*_*ach 6 sql postgresql column-alias

我可以修改使用的列别名下一avg_timecnt在表达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;
Run Code Online (Sandbox Code Playgroud)

它将引发下一个错误:

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

但是,下一个可以正常工作(使用主表达式而不是列别名:

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;
Run Code Online (Sandbox Code Playgroud)

Use*_*ady 9

查询的执行顺序(以及表达式和别名的求值)与其编写的方式不同。“一般”立场是按以下顺序评估子句:

FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
Run Code Online (Sandbox Code Playgroud)

因此,在 select 子句完成之前,大多数查询都不知道列别名(这就是您可以在 ORDER BY 子句中使用别名的原因)。然而,在 from 子句中建立的表别名可以在 where to order by 子句中理解。

最常见的解决方法是将查询封装到“派生表”中

建议阅读:SQL 查询的执行顺序

注意:不同的 SQL dbms 对于别名的使用有不同的具体规则

编辑 提醒读者逻辑子句序列背后的目的是,通常(但并非总是)别名仅在声明别名的子句之后才变得可引用。最常见的是子句中声明的别名SELECT可以被子句使用ORDER BY。特别是,子句中声明的别名SELECT不能在同一SELECT子句中引用。

但请注意,由于产品的差异,并非每个 dbms 都会以这种方式运行


Jua*_*eza 6

您可以在GROUP BYor HAVING语句中使用先前创建的别名,但不能在SELECTor WHERE语句中使用。这是因为程序同时处理所有SELECT语句,并且尚不知道别名的值。

解决方案是将查询封装在子查询中,然后在外部使用别名。

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;
Run Code Online (Sandbox Code Playgroud)