Orden de ejecución de las cláusulas de las sentencias SELECT de SQL

Escrito por el .
planeta-codigo programacion
Comentarios

PostgreSQL
MySQL

El lenguaje SQL es un potente lenguaje declarativo usado en las bases de datos relacionales como MySQL o PostgreSQL. En el lenguaje SQL se declara que datos se quieren recuperar, qué condiciones han de cumplir cumplir y qué funciones se aplican a los datos pero no se define como han de recuperarse los datos, es la base de datos la que decide como guardarlos e interpretando la sentencia SQL la que decide cómo recuperarlos.

El lenguaje SQL se compone de diferentes tipos de sentencias según el tipo de operación, lectura de datos con SELECT, inserción de datos con INSERT, actualización con UPDATE y eliminación con DELETE.

Las sentencias SELECT tienen la siguiente sintaxis en PostgreSQL.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    [ * | expression [ [ AS ] output_name ] [, ...] ]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ GROUP BY grouping_element [, ...] ]
    [ HAVING condition [, ...] ]
    [ WINDOW window_name AS ( window_definition ) [, ...] ]
    [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
    [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
    [ LIMIT { count | ALL } ]
    [ OFFSET start [ ROW | ROWS ] ]
    [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
    [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ]

where from_item can be one of:

    [ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
                [ TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ] ]
    [ LATERAL ] ( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
    with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
    [ LATERAL ] function_name ( [ argument [, ...] ] )
                [ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
    [ LATERAL ] function_name ( [ argument [, ...] ] ) [ AS ] alias ( column_definition [, ...] )
    [ LATERAL ] function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )
    [ LATERAL ] ROWS FROM( function_name ( [ argument [, ...] ] ) [ AS ( column_definition [, ...] ) ] [, ...] )
                [ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
    from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]

and grouping_element can be one of:

    ( )
    expression
    ( expression [, ...] )
    ROLLUP ( { expression | ( expression [, ...] ) } [, ...] )
    CUBE ( { expression | ( expression [, ...] ) } [, ...] )
    GROUPING SETS ( grouping_element [, ...] )

and with_query is:

    with_query_name [ ( column_name [, ...] ) ] AS ( select | values | insert | update | delete )

TABLE [ ONLY ] table_name [ * ]

La sentencia SELECT se compone de varias cláusulas que se interpretan siguiendo una secuencia de operaciones tal que:

  1. FROM: obtener los registros de todas las tablas fuentes de dato. Si hay subqueries en la cláusula FROM son evaluadas primero.
  2. JOIN: Realizar todas las posibles combinaciones descartando aquellas combinaciones que no cumplen las condiciones JOIN o estableciendo NULL en caso de outer joins.
  3. WHERE: Filtrar las combinaciones que cumplen las condiciones de la cláusula WHERE.
  4. GROUP BY: Construir los grupos basados en las expresiones de la lista de la cláusulas GROUP BY.
  5. HAVING: Filtrar los grupos que cumplen las condiciones de la cláusula HAVING.
  6. SELECT: Evaluar las expresiones de la lista SELECT para seleccionar los datos.
  7. DISTINCT: Eliminar filas duplicadas si se especifica DISTINCT.
  8. UNION, EXCEPT, INTERSECT: Aplicar las operaciones UNION, EXCEPT e INTERSECT.
  9. ORDER BY: Ordenar las filas de acuerdo a la cláusula ORDER BY.
  10. OFFSET, LIMIT: Descartar los registros de acuerdo OFFSET y LIMIT.

Este es el orden general pero el algoritmo del planificador puede optimizar estos pasos realizándose en diferente orden o incluso simultáneamente. Por ejemplo, si se especifica un límite de 1 no es necesario obtener todas las filas de las tablas fuente sino solo una que cumpla la condición WHERE.