Why can't I use column aliases in the next SELECT expression?

允我心安 提交于 2019-11-27 09:46:06
Juan Carlos Oropeza

You can use a previous created alias in the GROUP BY or HAVING but not in SELECT or WHERE that is because the instruction proces all part of the SELECT at the same time and the query doesnt know that value yet.

The solution is encapsulate the query in a sub query and then the alias are available outside.

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;

Aliases are not available until the virtual relation is actually created, if you want to do additional expressions using the aliases themselves you will have to create the virtual relation using as sub-query than run an additional query on top of it. So I would modify your query to the following:

SELECT stddev_time, max_time, avg_time, min_time, ROUND(avg_time * cnt, 2) as slowdown, path 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, 
    ROUND(AVG(time) * COUNT(path), 2) as slowdown, path
FROM 
    loadtime
GROUP BY
    path
ORDER BY
    avg_time DESC
LIMIT 10;
)

I want to add here the reason your second query worked is because the query planner recognized those columns as defined directly in the table you're querying them from.

Used_By_Already

The order of execution of a query is NOT the same as the way it is written. The "general" position is that the clauses are evaluated in this sequence:

FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY

Hence the column aliases are unknown to most of the query until the select clause is complete (and this is why you can use aliases in the ORDER BY clause). However table aliases which are established in the from clause are understood in the where to order by clauses.

The most common workaround is to encapsulate your query into a "derived table"

Suggested reading: Order Of Execution of the SQL query

Note: different SQL dbms have different specific rules regarding use of alises

Either repeat the expressions:

ROUND(ROUND(AVG(time), 2) * COUNT(path), 2) as slowdown

or use an subquery:

SELECT *, 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) x
ORDER BY avg_time DESC
LIMIT 10;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!