What Is the Order of Execution for This SQL Statement

Order Of Execution of the SQL query

SQL is a declarative language. The result of a query must be what you would get if you evaluated as follows (from Microsoft):

Logical Processing Order of the SELECT statement

The following steps show the logical
processing order, or binding order,
for a SELECT statement. This order
determines when the objects defined in
one step are made available to the
clauses in subsequent steps. For
example, if the query processor can
bind to (access) the tables or views
defined in the FROM clause, these
objects and their columns are made
available to all subsequent steps.
Conversely, because the SELECT clause
is step 8, any column aliases or
derived columns defined in that clause
cannot be referenced by preceding
clauses. However, they can be
referenced by subsequent clauses such
as the ORDER BY clause. Note that the
actual physical execution of the
statement is determined by the query
processor and the order may vary from
this list.

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBE or WITH ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP

The optimizer is free to choose any order it feels appropriate to produce the best execution time. Given any SQL query, is basically impossible to anybody to pretend it knows the execution order. If you add detailed information about the schema involved (exact tables and indexes definition) and the estimated cardinalities (size of data and selectivity of keys) then one can take a guess at the probable execution order.

Ultimately, the only correct 'order' is the one described ion the actual execution plan. See Displaying Execution Plans by Using SQL Server Profiler Event Classes and Displaying Graphical Execution Plans (SQL Server Management Studio).

A completely different thing though is how do queries, subqueries and expressions project themselves into 'validity'. For instance if you have an aliased expression in the SELECT projection list, can you use the alias in the WHERE clause? Like this:

SELECT a+b as c
FROM t
WHERE c=...;

Is the use of c alias valid in the where clause? The answer is NO. Queries form a syntax tree, and a lower branch of the tree cannot be reference something defined higher in the tree. This is not necessarily an order of 'execution', is more of a syntax parsing issue. It is equivalent to writing this code in C#:

void Select (int a, int b)
{
if (c = ...) then {...}
int c = a+b;
}

Just as in C# this code won't compile because the variable c is used before is defined, the SELECT above won't compile properly because the alias c is referenced lower in the tree than is actually defined.

Unfortunately, unlike the well known rules of C/C# language parsing, the SQL rules of how the query tree is built are somehow esoteric. There is a brief mention of them in Single SQL Statement Processing but a detailed discussion of how they are created, and what order is valid and what not, I don't know of any source. I'm not saying there aren't good sources, I'm sure some of the good SQL books out there cover this topic.

Note that the syntax tree order does not match the visual order of the SQL text. For example the ORDER BY clause is usually the last in the SQL text, but as a syntax tree it sits above everything else (it sorts the output of the SELECT, so it sits above the SELECTed columns so to speak) and as such is is valid to reference the c alias:

SELECT a+b as c
FROM t
ORDER BY c;

SQL Order of execution vs Order of writing

SQL is a declarative language, not a procedural language. That means that the SQL compiler and optimizer determine what operations are actually run. These operations typically take the form of a directed acyclic graph (DAG) of operations.

The operators have no obvious relationship to the original query -- except that the results it generates are guaranteed to be the same. In terms of execution there are no clauses, just things like "hash join" and "filter" and "sort" -- or whatever the database implements for the DAG.

You are confusing execution with compilation and probably you just care about scoping rules.

So, to start with SQL has a set of clauses and these are in a very specified order. Your question contains this ordering -- at least for a database that supports those clauses.

The second part is the ordering for identifying identifiers. Basically, this comes down to:

  • Table aliases are defined in the FROM clause. So this can be considered as "first" for scoping purposes.
  • Column aliases are defined in the SELECT clause. By the SQL Standard, column aliases can be used in the ORDER BY. Many databases extend this to the QUALIFY (if supported), HAVING, and GROUP BY clauses. In general, databases do not support them in the WHERE clause.
  • If two tables in the FROM have the same column name, then the column has to be qualified to identify the table. The one exception to this is when the column is a key in a JOIN and the USING clause is used. Then the unqualified column name is fine.
  • If a column alias defined in the SELECT conflicts with a table alias in a clause that supports column aliases, then it is up to the database which to choose.

What is the order of execution of a function in an sql query?

In the first example it will only be executed 100 times. You can verify that by adding a debugging call in the function:

create table mytable (a, b) as select mod(level, 10), level from dual connect by level <= 50;

create or replace function myfunction(p number)
return number as
begin
dbms_output.put_line('In function for p=' || p);
return mod(p,3);
end;
/

set serveroutput on

select myfunction(b)
from mytable
where a = 1;

MYFUNCTION(B)
-------------
1
2
0
1
2

In function for p=1
In function for p=11
In function for p=21
In function for p=31
In function for p=41

The function is only called for the rows that match the where clause filter. However, as far as I know that isn't guaranteed.

It's rather more complicated in the second example, and is largely up to the optimiser. For my simple demo the optimiser (11gR2 in this case) is evaluating a first, and only calls the function for the rows that match that; but it then calls it again for the select-list value:

select myfunction(b)
from mytable
where a = 1
and myfunction(b) = 2;

MYFUNCTION(B)
-------------
2
2

In function for p=1
In function for p=11
In function for p=11
In function for p=21
In function for p=31
In function for p=41
In function for p=41

The function is called for each of the five rows where a=1 as before, and for those where myfunction(b) = 2 it is called a second time, to get the value in the result set.

Again, for this example, things you might think would change this behaviour don't. All of these get exactly the same output:

select myfunction(b)
from mytable
where myfunction(b) = 2
and a = 1;

select x
from (
select myfunction(b) as x
from mytable
where a = 1
)
where x = 2;

select x
from (
select /*+ materialize */ myfunction(b) as x
from mytable
where a = 1
)
where x = 2;

with t (x) as (
select myfunction(b)
from mytable
where a = 1
)
select x
from t
where x = 2;

The optimiser is internally rewriting them all into the same query, and you still get all seven function calls. Adding an undocumented hint does change it:

with t (x) as (
select /*+ materialize */ myfunction(b)
from mytable
where a = 1
)
select x
from t
where x = 2;

X
----------
2
2

In function for p=1
In function for p=11
In function for p=21
In function for p=31
In function for p=41

but you can't (or shouldn't) really use or rely on that.

The indexing, partitioning, the optimiser version, stats, etc. will all affect how the optimiser behaves for your query.

And as other things to consider, you could have a function-based index, or a deterministic function...

So... it depends.

Is there any specific order of execution in SQL query?

There is a logical order to evaluation of the query text, but the database engine can choose what order execute the query components based upon what is most optimal. The logical text parsing ordering is listed below. That is, for example, why you can't use an alias from SELECT clause in a WHERE clause. As far as the query parsing process is concerned, the alias doesn't exist yet.

  1. FROM

  2. ON

  3. OUTER

  4. WHERE

  5. GROUP BY

  6. CUBE | ROLLUP (these are not present in MySQL but are in some other SQL dialects)

  7. HAVING

  8. SELECT

  9. DISTINCT

  10. ORDER BY

  11. LIMIT (or, in MSSQL, TOP)

See the Microsoft documentation (see "Logical Processing Order of the SELECT statement") for more information on this.

What's the execute order of the different parts of a SQL select statement?

Have a look at

SQL SERVER – Logical Query Processing Phases – Order of Statement Execution

  1. FROM
  2. ON
  3. OUTER
  4. WHERE
  5. GROUP BY
  6. CUBE | ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP

Also, for some good info see Logical Query Processing



Related Topics



Leave a reply



Submit