Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Can I modify the next to use the column aliases avg_time and cnt in an expression 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;

It raises the next error:

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

The next, however, works fine (use primary expressions instead of column aliases:

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;
like image 386
sergzach Avatar asked Jan 22 '16 21:01

sergzach


People also ask

Can we use column alias in SELECT statement?

Alias is used to give a temporary name(only for the duration of the query) to the column or table in order to make the column name or table name more readable. It does not change the name of the column permanently.

Can alias be used in expression?

Aliases are often used to name a column that is the result of an arithmetic expression or summary function. An alias is one word only. If you need a longer column name, then use the LABEL= column-modifier, as described in column-modifier.

Which of the following character is not allowed in giving column expression alias?

Oracle strongly discourages you from using $ and # in nonquoted identifiers.

Are column aliases allowed in JOIN conditions?

No, you cannot do that. The alias is not bound until later in the processing. You can use "Nombre" in an ORDER BY, but not in a WHERE clause and certainly not in a JOIN clause.


2 Answers

The order of execution of a query (and thus the evaluation of expressions and aliases) 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 aliases

EDIT The purpose behind reminding readers of the logical clause sequence is that often (but not always) aliases only becomes referable AFTER the clause where the alias is declared. The most common of which is that aliases declared in the SELECT clause can be used by the ORDER BY clause. In particular, an alias declared in a SELECT clause cannot be referenced within the same SELECT clause.

But please do note that due to differences in products not every dbms will behave in this manner

like image 157
Paul Maxwell Avatar answered Oct 14 '22 18:10

Paul Maxwell


You can use a previously created alias in the GROUP BY or HAVING statement but not in a SELECT or WHERE statement. This is because the program processes all of the SELECT statement at the same time and doesn't know the alias' value yet.

The solution is to encapsulate the query in a subquery and then the alias is 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;
like image 34
Juan Carlos Oropeza Avatar answered Oct 14 '22 17:10

Juan Carlos Oropeza