๐ฆ๐ค๐ ๐ค๐๐ฒ๐ฟ๐ถ๐ฒ๐ ๐๐ผ๐ป'๐ ๐ฆ๐๐ฎ๐ฟ๐ ๐ช๐ถ๐๐ต ๐ฆ๐๐๐๐๐ง
We usually start with SQL by entering SELECT, but it is not executed first. SELECT actually gets executed as the 5th step.
This explains why some SQL statements work while others donโt.
Here is the actual execution order:
๐ญ. ๐๐ฅ๐ข๐ /๐๐ข๐๐ก โ Tables are merged to form the basis of the data set. All ON conditions are assessed at this point
๐ฎ. ๐ช๐๐๐ฅ๐ โ Rows are filtered before any grouping takes place. You cannot refer to any aggregates at this point because none have been created yet
๐ฏ. ๐๐ฅ๐ข๐จ๐ฃ ๐๐ฌ โ The remaining rows are grouped. After this step, you're working with groups rather than individual rows
๐ฐ. ๐๐๐ฉ๐๐ก๐ โ Groups get filtered. This is where you can filter on aggregate results like ๐๐ข๐จ๐ก๐ง(*) > ๐ฑ
๐ฑ. ๐ฆ๐๐๐๐๐ง โ Columns are computed and returned. Window functions run here too
๐ฒ. ๐ข๐ฅ๐๐๐ฅ ๐๐ฌ โ Results are sorted. This runs after SELECT, so you can use aliases in your sorting
๐ณ. ๐๐๐ ๐๐ง โ Output is capped to the specified row count
This order answers common debugging questions. Can you filter on a window function result in a WHERE clause? No, window functions run in SELECT, which happens after WHERE.
Can you use a GROUP BY alias in ORDER BY? Yes, ORDER BY runs last. This is also why ๐ฃ๐ผ๐๐๐ด๐ฟ๐ฒ๐, ๐ ๐๐ฆ๐ค๐, and ๐ฆ๐ค๐ ๐ฆ๐ฒ๐ฟ๐๐ฒ๐ฟ all reject ๐ช๐๐๐ฅ๐ ๐๐ข๐จ๐ก๐ง(*) > ๐ฑ, as the aggregate doesn't exist at that stage.
Database engines optimize heavily and may reorder operations for performance. But this logical order determines what's valid SQL.