0

I understand that the order or execution is as follows

FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE or WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP

from this SO Answer as well as Microsoft Documentation

However, in my query below, the column total is built on the fly which is later used in having clause. This would mean that having executes AFTER select and not before because the column 'total' does not exist in orders table.

Am I interpreting it wrong or simply missing something?

Query

select customer_id, 
        sum(CASE
        WHEN product_name = 'A' THEN 1
        WHEN product_name = 'B' THEN 1
        WHEN product_name = 'C' THEN -1
        ELSE 0 END
        ) as total  
from Orders
group by customer_id
having total > 1;

Orders table

+------------+-------------+--------------+
|   order_id | customer_id | product_name |
+------------+-------------+--------------+
|         10 |           1 | A            |
|         20 |           1 | B            |
|         30 |           1 | D            |
|         40 |           1 | C            |
|         50 |           2 | A            |
|         60 |           3 | A            |
|         70 |           3 | B            |
|         80 |           3 | D            |
|         90 |           4 | C            |
+------------+-------------+--------------+

Result

+-------------+-------+
| customer_id | total |
+-------------+-------+
|           3 |     2 |
+-------------+-------+
Pirate X
  • 3,023
  • 5
  • 33
  • 60
  • 1
    Your query is invalid, you can't reference a computed column in your having clause, you have to reproduce the computation. – Dale K May 03 '20 at 20:38
  • 2
    Are you saying that you are getting the result when running your query? With SQL Server this should not be possible. Are you running it in MySQL maybe? MySQL, unlike the SQL standard, allows alias names in the `HAVING` clause. – Thorsten Kettner May 03 '20 at 20:44
  • @ThorstenKettner You're right. I was utilizing an online sql fiddle where it was switched to mysql. That was the issue. Thanks !! – Pirate X May 03 '20 at 20:46

1 Answers1

2

What you have described is NOT the "order of execution". It is the order of scoping for identifiers defined in the query.

It is saying that an identifier defined in from is known in the clauses beneath it. Similarly, an identifier defined in the select is not recognized in the having. I should note that many databases do allow the having clause to use aliases in the having clause. SQL Server is not one of them.

SQL is a descriptive language, not a procedural language. That means that a query describes the result set. It does not state the steps used to generate the result. The compiler and optimizer produce the execution plan, which looks nothing like the original query.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786