SELECT

SELECT, TABLE, WITH — recuperar filas de una tabla o vista

Synopsis

[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    [ { * | expression [ [ AS ] output_name ] } [, ...] ]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ GROUP BY [ ALL | DISTINCT ] 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 | WITH TIES } ]
    [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF from_reference [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ]

donde from_item puede ser uno de:

    [ 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 join_type from_item { ON join_condition | USING ( join_column [, ...] ) [ AS join_using_alias ] }
    from_item NATURAL join_type from_item
    from_item CROSS JOIN from_item

y grouping_element puede ser uno de:

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

y with_query es:

    with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ] ( select | values | insert | update | delete | merge )
        [ SEARCH { BREADTH | DEPTH } FIRST BY column_name [, ...] SET search_seq_col_name ]
        [ CYCLE column_name [, ...] SET cycle_mark_col_name [ TO cycle_mark_value DEFAULT cycle_mark_default ] USING cycle_path_col_name ]

TABLE [ ONLY ] table_name [ * ]

Descripción

SELECT recupera filas de cero o más tablas. El procesamiento general de SELECT es el siguiente:

  1. Se computan todas las consultas en la lista WITH. Estas funcionan efectivamente como tablas temporales que pueden ser referenciadas en la lista FROM. Una consulta WITH que es referenciada más de una vez en FROM se computa una sola vez, a menos que se especifique lo contrario con NOT MATERIALIZED. (Consulta Cláusula WITH más abajo).

  2. Se computan todos los elementos en la lista FROM. (Cada elemento en la lista FROM es una tabla real o virtual). Si se especifica más de un elemento en la lista FROM, se realiza un producto cruzado (cross-join) entre ellos. (Consulta Cláusula FROM más abajo).

  3. Si se especifica la cláusula WHERE, todas las filas que no cumplen la condición son eliminadas del resultado. (Consulta WHERE Clause más abajo).

  4. Si se especifica la cláusula GROUP BY, o si hay llamadas a funciones de agregación, el resultado se combina en grupos de filas que coinciden en uno o más valores, y se calculan los resultados de las funciones de agregación. Si la cláusula HAVING está presente, esta elimina los grupos que no cumplen con la condición dada. (Consulta GROUP BY Clause y HAVING Clause más abajo). Aunque las columnas de salida de la consulta se computan nominalmente en el siguiente paso, también pueden ser referenciadas (por nombre o número ordinal) en la cláusula GROUP BY.

  5. Las filas de salida reales se computan utilizando las expresiones de salida de SELECT para cada fila o grupo de filas seleccionado. (Consulta SELECT List más abajo).

  6. SELECT DISTINCT elimina las filas duplicadas del resultado. SELECT DISTINCT ON elimina las filas que coinciden en todas las expresiones especificadas. SELECT ALL (por defecto) devolverá todas las filas candidatas, incluyendo duplicados. (Consulta DISTINCT Clause más abajo).

  7. Utilizando los operadores UNION, INTERSECT y EXCEPT, se puede combinar el resultado de más de una sentencia SELECT para formar un único conjunto de resultados. El operador UNION devuelve todas las filas que están en uno o en ambos conjuntos de resultados. El operador INTERSECT devuelve todas las filas que están estrictamente en ambos conjuntos de resultados. El operador EXCEPT devuelve las filas que están en el primer conjunto de resultados pero no en el segundo. En los tres casos, las filas duplicadas son eliminadas a menos que se especifique ALL. Se puede añadir la palabra clave opcional DISTINCT para especificar explícitamente la eliminación de filas duplicadas. Ten en cuenta que DISTINCT es el comportamiento por defecto aquí, a pesar de que ALL es el valor predeterminado para el propio SELECT. (Consulta UNION Clause, INTERSECT Clause y EXCEPT Clause más abajo).

  8. Si se especifica la cláusula ORDER BY, las filas devueltas se ordenan en el orden especificado. Si no se proporciona ORDER BY, las filas se devuelven en el orden que el sistema considere más rápido de producir. (Consulta ORDER BY Clause más abajo).

  9. Si se especifica la cláusula LIMIT (o FETCH FIRST) o OFFSET, la sentencia SELECT solo devuelve un subconjunto de las filas del resultado. (Consulta LIMIT Clause más abajo).

  10. Si se especifica FOR UPDATE, FOR NO KEY UPDATE, FOR SHARE o FOR KEY SHARE, la sentencia SELECT bloquea las filas seleccionadas contra actualizaciones concurrentes. (Consulta The Locking Clause más abajo).

Debes tener el privilegio SELECT en cada columna utilizada en un comando SELECT. El uso de FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE o FOR KEY SHARE requiere también el privilegio UPDATE (para al menos una columna de cada tabla seleccionada de esa manera).

Parámetros

Cláusula WITH

La cláusula WITH te permite especificar una o más subconsultas que pueden ser referenciadas por nombre en la consulta principal. Las subconsultas actúan efectivamente como tablas o vistas temporales durante la ejecución de la consulta principal. Cada subconsulta puede ser una sentencia SELECT, TABLE, VALUES, INSERT, UPDATE, DELETE o MERGE. Al escribir una sentencia de modificación de datos (INSERT, UPDATE, DELETE o MERGE) en WITH, es habitual incluir una cláusula RETURNING. Es el resultado de RETURNING, y no la tabla subyacente que la sentencia modifica, lo que forma la tabla temporal que es leída por la consulta principal. Si se omite RETURNING, la sentencia se sigue ejecutando, pero no produce ninguna salida, por lo que no puede ser referenciada como una tabla por la consulta principal.

Se debe especificar un nombre (sin calificación de esquema) para cada consulta WITH. Opcionalmente, se puede especificar una lista de nombres de columnas; si se omite, los nombres de las columnas se infieren de la subconsulta.

Si se especifica RECURSIVE, se permite que una subconsulta SELECT se referencie a sí misma por nombre. Dicha subconsulta debe tener la forma

non_recursive_term UNION [ ALL | DISTINCT ] recursive_term

donde la autoreferencia recursiva debe aparecer en el lado derecho del UNION. Solo se permite una autoreferencia recursiva por consulta. No se admiten sentencias recursivas de modificación de datos, pero puedes utilizar los resultados de una consulta SELECT recursiva en una sentencia de modificación de datos. Consulta la Section 7.8 para ver un ejemplo.

Otro efecto de RECURSIVE es que las consultas WITH no necesitan estar ordenadas: una consulta puede referenciar a otra que esté más adelante en la lista. (Sin embargo, las referencias circulares o la recursividad mutua no están implementadas). Sin RECURSIVE, las consultas WITH solo pueden referenciar a consultas WITH compañeras que estén antes en la lista WITH.

Cuando hay múltiples consultas en la cláusula WITH, RECURSIVE debe escribirse una sola vez, inmediatamente después de WITH. Se aplica a todas las consultas en la cláusula WITH, aunque no tiene efecto en aquellas consultas que no utilizan recursividad ni referencias hacia adelante.

La cláusula opcional SEARCH computa una columna de secuencia de búsqueda que se puede utilizar para ordenar los resultados de una consulta recursiva en orden de anchura primero (breadth-first) o profundidad primero (depth-first). La lista de nombres de columnas proporcionada especifica la clave de fila que se utilizará para hacer el seguimiento de las filas visitadas. Se añadirá una columna llamada search_seq_col_name a la lista de columnas de resultados de la consulta WITH. Esta columna se puede ordenar en la consulta externa para lograr el ordenamiento correspondiente. Consulta la Section 7.8.2.1 para ver ejemplos.

La cláusula opcional CYCLE se utiliza para detectar bucles (ciclos) en consultas recursivas. La lista de nombres de columnas proporcionada especifica la clave de fila que se utilizará para hacer el seguimiento de las filas visitadas. Se añadirá una columna llamada cycle_mark_col_name a la lista de columnas de resultados de la consulta WITH. Esta columna se establecerá en cycle_mark_value cuando se haya detectado un ciclo, y en caso contrario en cycle_mark_default. Además, el procesamiento de la unión recursiva se detendrá cuando se haya detectado un ciclo. cycle_mark_value y cycle_mark_default deben ser constantes y coercibles a un tipo de datos común, y dicho tipo de datos debe tener un operador de desigualdad. (El estándar SQL requiere que sean constantes booleanas o cadenas de caracteres, pero PostgreSQL no lo exige). Por defecto, se utilizan TRUE y FALSE (de tipo boolean). Además, se añadirá una columna llamada cycle_path_col_name a la lista de columnas de resultados de la consulta WITH. Esta columna se utiliza internamente para el seguimiento de las filas visitadas. Consulta la Section 7.8.2.2 for examples.

Tanto la cláusula SEARCH como la cláusula CYCLE solo son válidas para consultas WITH recursivas. La with_query debe ser un UNION (o UNION ALL) de dos comandos SELECT (o equivalentes) sin UNIONs anidados. Si se utilizan ambas cláusulas, la columna añadida por la cláusula SEARCH aparece antes de las columnas añadidas por la cláusula CYCLE.

La consulta principal y las consultas WITH se ejecutan todas (nocionalmente) al mismo tiempo. Esto implica que los efectos de una sentencia de modificación de datos en WITH no se pueden ver desde otras partes de la consulta, a menos que sea leyendo su salida RETURNING. Si dos de estas sentencias de modificación de datos intentan modificar la misma fila, los resultados son indeterminados.

Una propiedad clave de las consultas WITH es que normalmente se evalúan una sola vez por ejecución de la consulta principal, incluso si la consulta principal se refiere a ellas más de una vez. En particular, se garantiza que las sentencias de modificación de datos se ejecutan una y solo una vez, independientemente de si la consulta principal lee toda, parte o ninguna de su salida.

Sin embargo, una consulta WITH se puede marcar como NOT MATERIALIZED para eliminar esta garantía. En ese caso, la consulta WITH se puede integrar (fold) en la consulta principal de forma muy similar a como si fuera una subconsulta SELECT simple en la cláusula FROM de la consulta principal. Esto provoca cómputos duplicados si la consulta principal se refiere a esa consulta WITH más de una vez; pero si cada uno de esos usos requiere solo unas pocas filas de la salida total de la consulta WITH, NOT MATERIALIZED puede proporcionar un ahorro neto al permitir que las consultas se optimicen conjuntamente. NOT MATERIALIZED se ignora si se asocia a una consulta WITH que es recursiva o que no está libre de efectos secundarios (es decir, que no es un SELECT simple que no contenga funciones volátiles).

Por defecto, una consulta WITH libre de efectos secundarios se integra en la consulta principal si se utiliza exactamente una vez en la cláusula FROM de la consulta principal. Esto permite la optimización conjunta de los dos niveles de consulta en situaciones donde eso debería ser semánticamente invisible. Sin embargo, dicha integración se puede evitar marcando la consulta WITH como MATERIALIZED. Eso podría ser útil, por ejemplo, si la consulta WITH se está utilizando como una barrera de optimización (optimization fence) para evitar que el planificador elija un mal plan. Las versiones de PostgreSQL anteriores a la v12 nunca realizaban dicha integración, por lo que las consultas escritas para versiones anteriores podrían depender de que WITH actúe como una barrera de optimización.

Cláusula FROM

La cláusula FROM especifica una o más tablas origen para el SELECT. Si se especifican múltiples orígenes, el resultado es el producto cartesiano (cross join) de todos los orígenes. Pero normalmente se añaden condiciones de calificación (a través de WHERE) para restringir las filas devueltas a un pequeño subconjunto del producto cartesiano.

La cláusula FROM puede contener los siguientes elementos:

table_name

El nombre (opcionalmente calificado por esquema) de una tabla o vista existente. Si se especifica ONLY antes del nombre de la tabla, solo se escanea esa tabla. Si no se especifica ONLY, se escanean la tabla y todas sus tablas descendientes (si las hay). Opcionalmente, se puede especificar * después del nombre de la tabla para indicar explícitamente que se incluyen las tablas descendientes.

alias

Un nombre sustituto para el elemento FROM que contiene el alias. Un alias se utiliza por brevedad o para eliminar la ambigüedad en las autouniones (self-joins, donde la misma tabla se escanea múltiples veces). Cuando se proporciona un alias, este oculta completamente el nombre real de la tabla o función; por ejemplo, dado FROM foo AS f, el resto del SELECT debe referirse a este elemento FROM como f y no como foo. Si se escribe un alias, también se puede escribir una lista de alias de columna para proporcionar nombres sustitutos para una o más columnas de la tabla.

TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ]

Una cláusula TABLESAMPLE después de un table_name indica que se debe utilizar el sampling_method especificado para recuperar un subconjunto de las filas de esa tabla. Este muestreo precede a la aplicación de cualquier otro filtro como las cláusulas WHERE. La distribución estándar de PostgreSQL incluye dos métodos de muestreo, BERNOULLI y SYSTEM, y se pueden instalar otros métodos de muestreo en la base de datos mediante extensiones.

Los métodos de muestreo BERNOULLI y SYSTEM aceptan cada uno un único argument que es la fracción de la tabla a muestrear, expresada como un porcentaje entre 0 y 100. Este argumento puede ser cualquier expresión con valor de tipo real. (Otros métodos de muestreo podrían aceptar más argumentos o argumentos diferentes). Estos dos métodos devuelven cada uno una muestra elegida al azar de la tabla que contendrá aproximadamente el porcentaje especificado de las filas de la tabla. El método BERNOULLI escanea toda la tabla y selecciona o ignora filas individuales de forma independiente con la probabilidad especificada. El método SYSTEM realiza un muestreo a nivel de bloque, teniendo cada bloque la probabilidad especificada de ser seleccionado; se devuelven todas las filas de cada bloque seleccionado. El método SYSTEM es significativamente más rápido que el método BERNOULLI cuando se especifican porcentajes de muestreo pequeños, pero puede devolver una muestra menos aleatoria de la tabla como resultado de los efectos de agrupación (clustering).

La cláusula opcional REPEATABLE especifica un número o expresión seed (semilla) a utilizar para generar números aleatorios dentro del método de muestreo. El valor de la semilla puede ser cualquier valor de punto flotante no nulo. Dos consultas que especifiquen la misma semilla y los mismos valores de argument seleccionarán la misma muestra de la tabla, si la tabla no ha sido modificada mientras tanto. Pero diferentes valores de semilla producirán usualmente muestras diferentes. Si no se proporciona REPEATABLE, se selecciona una nueva muestra aleatoria para cada consulta, basada en una semilla generada por el sistema. Ten en cuenta que algunos métodos de muestreo adicionales no aceptan REPEATABLE y siempre producirán muestras nuevas en cada uso.

select

Un sub-SELECT puede aparecer en la cláusula FROM. Esto actúa como si su salida se creara como una tabla temporal durante la ejecución de este único comando SELECT. Ten en cuenta que el sub-SELECT debe estar rodeado por paréntesis, y se puede proporcionar un alias de la misma manera que para una tabla. También se puede utilizar aquí un comando VALUES.

with_query_name

Una consulta WITH se referiencia escribiendo su nombre, tal como si el nombre de la consulta fuera un nombre de tabla. (De hecho, la consulta WITH oculta cualquier tabla real del mismo nombre para los propósitos de la consulta principal. Si es necesario, puedes hacer referencia a una tabla real del mismo nombre calificando con el esquema el nombre de la tabla). Se puede proporcionar un alias de la misma manera que para una tabla.

function_name

Las llamadas a funciones pueden aparecer en la cláusula FROM. (Esto es especialmente útil para funciones que devuelven conjuntos de resultados, pero se puede utilizar cualquier función). Esto actúa como si la salida de la función se creara como una tabla temporal durante la ejecución de este único comando SELECT. Si el tipo de resultado de la función es compuesto (incluyendo el caso de una función con múltiples parámetros OUT), cada atributo se convierte en una columna separada en la tabla implícita.

Cuando se añade la cláusula opcional WITH ORDINALITY a la llamada de la función, se añadirá una columna adicional de tipo bigint a las columnas de resultado de la función. Esta columna enumera las filas del conjunto de resultados de la función, comenzando desde 1. Por defecto, esta columna se llama ordinality.

Se puede proporcionar un alias de la misma manera que para una tabla. Si se escribe un alias, también se puede escribir una lista de alias de columna para proporcionar nombres sustitutos para uno o más atributos del tipo de retorno compuesto de la función, incluyendo la columna de ordinalidad si está presente.

Se pueden combinar múltiples llamadas a funciones en un único elemento de la cláusula FROM rodeándolas con ROWS FROM( ... ). La salida de dicho elemento es la concatenación de la primera fila de cada función, luego la segunda fila de cada función, etc. Si algunas de las funciones producen menos filas que otras, se sustituyen los datos faltantes por valores nulos, de modo que el número total de filas devueltas sea siempre el mismo que para la función que produjo más filas.

Si la función se ha definido retornando el tipo de datos record, entonces debe estar presente un alias o la palabra clave AS, seguida de una lista de definiciones de columnas en la forma ( column_name data_type [, ... ]). La lista de definiciones de columnas debe coincidir con el número y los tipos reales de las columnas devueltas por la función.

Al utilizar la sintaxis ROWS FROM( ... ), si una de las funciones requiere una lista de definiciones de columnas, se prefiere colocar la lista de definiciones de columnas después de la llamada a la función dentro de ROWS FROM( ... ). Se puede colocar una lista de definiciones de columnas después del constructor ROWS FROM( ... ) solo si hay una única función y no hay cláusula WITH ORDINALITY.

Para utilizar ORDINALITY junto con una lista de definiciones de columnas, debes utilizar la sintaxis ROWS FROM( ... ) y colocar la lista de definiciones de columnas dentro de ROWS FROM( ... ).

join_type

Uno de

  • [ INNER ] JOIN

  • LEFT [ OUTER ] JOIN

  • RIGHT [ OUTER ] JOIN

  • FULL [ OUTER ] JOIN

Para los tipos de unión INNER y OUTER, se debe especificar una condición de unión, a saber, exactamente una de ON join_condition, USING (join_column [, ...]) o NATURAL. Consulta más abajo su significado.

Una cláusula JOIN combina dos elementos de la cláusula FROM, a los que por conveniencia nos referiremos como tablas, aunque en realidad pueden ser cualquier tipo de elemento FROM. Utiliza paréntesis si es necesario para determinar el orden de anidamiento. En ausencia de paréntesis, las uniones (JOINs) se anidan de izquierda a derecha. En cualquier caso, JOIN se asocia más fuertemente que las comas que separan los elementos de la lista FROM. Todas las opciones de JOIN son simplemente una conveniencia de notación, ya que no hacen nada que no se pudiera hacer con elementos simples en FROM y WHERE.

LEFT OUTER JOIN devuelve todas las filas en el producto cartesiano calificado (es decir, todas las filas combinadas que cumplen su condición de unión), más una copia de cada fila en la tabla de la izquierda para la cual no hubo ninguna fila de la derecha que cumpliera la condición de unión. Esta fila de la izquierda se extiende al ancho completo de la tabla unida insertando valores nulos para las columnas de la derecha. Ten en cuenta que solo se considera la condición propia de la cláusula JOIN al decidir qué filas tienen coincidencias. Las condiciones externas se aplican después.

Por el contrario, RIGHT OUTER JOIN devuelve todas las filas unidas, más una fila por cada fila de la derecha que no tenga coincidencia (extendida con nulos a la izquierda). Esto es solo una conveniencia de notación, ya que podrías convertirlo en un LEFT OUTER JOIN intercambiando las tablas de la izquierda y la derecha.

FULL OUTER JOIN devuelve todas las filas unidas, más una fila por cada fila de la izquierda que no tenga coincidencia (extendida con nulos a la derecha), más una fila por cada fila de la derecha que no tenga coincidencia (extendida con nulos a la izquierda).

ON join_condition

join_condition es una expresión que da como resultado un valor de tipo boolean (similar a una cláusula WHERE) que especifica cuáles filas en una unión se consideran coincidentes.

USING ( join_column [, ...] ) [ AS join_using_alias ]

Una cláusula de la forma USING ( a, b, ... ) es una abreviación de ON left_table.a = right_table.a AND left_table.b = right_table.b .... Además, USING implica que solo se incluirá una de cada par de columnas equivalentes en la salida de la unión, no ambas.

Si se especifica un nombre join_using_alias, este proporciona un alias de tabla para las columnas de unión. Solo las columnas de unión enumeradas en la cláusula USING son direccionables mediante este nombre. A diferencia de un alias regular, esto no oculta los nombres de las tablas unidas del resto de la consulta. También a diferencia de un alias regular, no puedes escribir una lista de alias de columna; los nombres de salida de las columnas de unión son los mismos que aparecen en la lista USING.

NATURAL

NATURAL es una abreviación para una lista USING que menciona todas las columnas de las dos tablas que tienen nombres coincidentes. Si no hay nombres de columnas comunes, NATURAL es equivalente a ON TRUE.

CROSS JOIN

CROSS JOIN es equivalente a INNER JOIN ON (TRUE), es decir, no se eliminan filas por calificación. Producen un producto cartesiano simple, el mismo resultado que obtienes al enumerar las dos tablas en el nivel superior de FROM, pero restringido por la condición de unión (si la hay).

LATERAL

La palabra clave LATERAL puede preceder a un elemento sub-SELECT en FROM. Esto permite que el sub-SELECT haga referencia a columnas de elementos FROM que aparecen antes de él en la lista FROM. (Sin LATERAL, cada sub-SELECT se evalúa de forma independiente y, por lo tanto, no puede hacer referencia cruzada a ningún otro elemento FROM).

LATERAL también puede preceder a un elemento de llamada a función en FROM, pero en este caso es una palabra de relleno, porque la expresión de la función puede hacer referencia a elementos anteriores de la cláusula FROM en cualquier caso.

Un elemento LATERAL puede aparecer en el nivel superior de la lista FROM, o dentro de un árbol de unión (JOIN). En este último caso, también puede hacer referencia a cualquier elemento que esté en el lado izquierdo de un JOIN del cual él mismo se encuentre en el lado derecho.

Cuando un elemento FROM contiene referencias cruzadas de tipo LATERAL, la evaluación procede de la siguiente manera: para cada fila del elemento FROM que proporciona la(s) columna(s) referenciada(s), o el conjunto de filas de múltiples elementos FROM que proporcionan las columnas, el elemento LATERAL se evalúa utilizando los valores de las columnas de esa fila o conjunto de filas. Las filas resultantes se unen de la manera habitual con las filas a partir de las cuales se calcularon. Esto se repite para cada fila o conjunto de filas de la(s) tabla(s) origen de las columnas.

La(s) tabla(s) origen de las columnas deben estar unidas mediante INNER o LEFT al elemento LATERAL; de lo contrario, no habría un conjunto de filas bien definido a partir del cual calcular cada conjunto de filas para el elemento LATERAL. Por lo tanto, aunque una construcción como X RIGHT JOIN LATERAL Y es sintácticamente válida, en realidad no está permitido que Y haga referencia a X.

Cláusula WHERE

La cláusula opcional WHERE tiene la forma general

WHERE condición

donde condición es cualquier expresión que se evalúe como un resultado de tipo boolean. Cualquier fila que no cumpla con esta condición será eliminada del resultado. Una fila cumple la condición si devuelve «true» cuando se sustituyen los valores reales de las filas en las referencias a variables.

Cláusula GROUP BY

La cláusula opcional GROUP BY tiene la forma general

GROUP BY [ ALL | DISTINCT ] elemento_de_agrupamiento [, ...]

GROUP BY condensará en una sola fila todas las filas seleccionadas que compartan los mismos valores para las expresiones agrupadas. Una expresión utilizada dentro de un elemento_de_agrupamiento puede ser el nombre de una columna de entrada, o el nombre o número ordinal de una columna de salida (elemento de la lista de SELECT), o una expresión arbitraria formada a partir de los valores de las columnas de entrada. En caso de ambigüedad, un nombre en GROUP BY se interpretará como el nombre de una columna de entrada en lugar del nombre de una columna de salida.

Si cualquiera de las opciones GROUPING SETS, ROLLUP o CUBE están presentes como elementos de agrupamiento, entonces la cláusula GROUP BY en su conjunto define un cierto número de conjuntos de agrupamiento (grouping sets) independientes. El efecto de esto es equivalente a construir un UNION ALL entre subconsultas con los conjuntos de agrupamiento individuales como sus cláusulas GROUP BY. La cláusula opcional DISTINCT elimina los conjuntos duplicados antes del procesamiento; no transforma el UNION ALL en un UNION DISTINCT. Para obtener más detalles sobre el manejo de los conjuntos de agrupamiento, consulta Section 7.2.4.

Las funciones de agregación, si se utiliza alguna, se calculan a través de todas las filas que componen cada grupo, produciendo un valor independiente para cada grupo. (Si hay funciones de agregación pero no hay cláusula GROUP BY, la consulta se trata como si tuviera un único grupo que comprende todas las filas seleccionadas). El conjunto de filas que se alimenta a cada función de agregación se puede filtrar aún más añadiendo una cláusula FILTER a la llamada de la función de agregación; consulta Section 4.2.7 para obtener más información. Cuando una cláusula FILTER está presente, solo las filas que coinciden con ella se incluyen en la entrada de esa función de agregación.

Cuando GROUP BY está presente, o hay funciones de agregación presentes, no es válido que las expresiones de la lista de SELECT hagan referencia a columnas no agrupadas, excepto dentro de las funciones de agregación o cuando la columna no agrupada depende funcionalmente de las columnas agrupadas, ya que de lo contrario habría más de un valor posible que devolver para una columna no agrupada. Existe una dependencia funcional si las columnas agrupadas (o un subconjunto de ellas) son la clave primaria de la tabla que contiene la columna no agrupada.

Ten en cuenta que todas las funciones de agregación se evalúan antes de evaluar cualquier expresión escalar en la cláusula HAVING o en la lista de SELECT. Esto significa que, por ejemplo, no se puede usar una expresión CASE para omitir la evaluación de una función de agregación; consulta Section 4.2.14.

Actualmente, no se pueden especificar FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE y FOR KEY SHARE con GROUP BY.

Cláusula HAVING

La cláusula opcional HAVING tiene la forma general

HAVING condición

donde condición es la misma que la especificada para la cláusula WHERE.

HAVING elimina las filas de grupo que no cumplen con la condición. HAVING es diferente de WHERE: WHERE filtra filas individuales antes de aplicar GROUP BY, mientras que HAVING filtra las filas de grupo creadas por GROUP BY. Cada columna referenciada en condición debe hacer referencia inequívoca a una columna de agrupamiento, a menos que la referencia aparezca dentro de una función de agregación o que la columna no agrupada sea dependiente funcionalmente de las columnas de agrupamiento.

La presencia de HAVING convierte una consulta en una consulta agrupada incluso si no hay una cláusula GROUP BY. Esto es lo mismo que ocurre cuando la consulta contiene funciones de agregación pero no hay cláusula GROUP BY. Se considera que todas las filas seleccionadas forman un único grupo, y la lista de SELECT y la cláusula HAVING solo pueden hacer referencia a columnas de la tabla desde el interior de funciones de agregación. Dicha consulta emitirá una sola fila si la condición de HAVING es verdadera, y cero filas si no lo es.

Actualmente, no se pueden especificar FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE y FOR KEY SHARE con HAVING.

Cláusula WINDOW

La cláusula opcional WINDOW tiene la forma general

WINDOW window_name AS ( window_definition ) [, ...]

donde window_name es un nombre al que se puede hacer referencia desde las cláusulas OVER o definiciones de ventana subsiguientes, y window_definition es

[ existing_window_name ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ frame_clause ]

Si se especifica un existing_window_name, este debe referirse a una entrada anterior en la lista de WINDOW; la nueva ventana copia su cláusula de partición de esa entrada, así como su cláusula de ordenamiento si la hubiera. En este caso, la nueva ventana no puede especificar su propia cláusula PARTITION BY, y puede especificar ORDER BY solo si la ventana copiada no tiene una. La nueva ventana siempre utiliza su propia cláusula de marco; la ventana copiada no debe especificar una cláusula de marco.

Los elementos de la lista PARTITION BY se interpretan de manera muy similar a los elementos de una cláusula GROUP BY, excepto que siempre son expresiones simples y nunca el nombre o número de una columna de salida. Otra diferencia es que estas expresiones pueden contener llamadas a funciones de agregación, las cuales no están permitidas en una cláusula GROUP BY normal. Se permiten aquí porque el procesamiento de ventanas ocurre después del agrupamiento y la agregación.

Del mismo modo, los elementos de la lista ORDER BY se interpretan de manera muy similar a los elementos de una cláusula ORDER BY a nivel de sentencia, excepto que las expresiones siempre se toman como expresiones simples y nunca como el nombre o número de una columna de salida.

La cláusula opcional frame_clause define el marco de ventana (window frame) para las funciones de ventana que dependen del marco (no todas lo hacen). El marco de ventana es un conjunto de filas relacionadas para cada fila de la consulta (llamada la fila actual). La frame_clause puede ser una de

{ RANGE | ROWS | GROUPS } frame_start [ frame_exclusion ]
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end [ frame_exclusion ]

donde frame_start y frame_end pueden ser uno de

UNBOUNDED PRECEDING
offset PRECEDING
CURRENT ROW
offset FOLLOWING
UNBOUNDED FOLLOWING

y frame_exclusion puede ser uno de

EXCLUDE CURRENT ROW
EXCLUDE GROUP
EXCLUDE TIES
EXCLUDE NO OTHERS

Si se omite frame_end, se establece por defecto en CURRENT ROW. Las restricciones son que frame_start no puede ser UNBOUNDED FOLLOWING, frame_end no puede ser UNBOUNDED PRECEDING, y la opción de frame_end no puede aparecer antes en la lista anterior de opciones de frame_start y frame_end que la opción de frame_start; por ejemplo RANGE BETWEEN CURRENT ROW AND offset PRECEDING no está permitido.

La opción de marco por defecto es RANGE UNBOUNDED PRECEDING, que es lo mismo que RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW; establece que el marco contiene todas las filas desde el inicio de la partición hasta el último par (peer) de la fila actual (una fila que la cláusula ORDER BY de la ventana considera equivalente a la fila actual; todas las filas son pares si no hay ORDER BY). En general, UNBOUNDED PRECEDING significa que el marco comienza con la primera fila de la partición, y de manera similar UNBOUNDED FOLLOWING significa que el marco termina con la última fila de la partición, independientemente del modo RANGE, ROWS o GROUPS. En el modo ROWS, CURRENT ROW significa que el marco comienza o termina con la fila actual; pero en el modo RANGE o GROUPS significa que el marco comienza o termina con el primer o último par de la fila actual en el ordenamiento ORDER BY. Las opciones offset PRECEDING y offset FOLLOWING varían en significado según el modo de marco. En el modo ROWS, el offset es un entero que indica que el marco comienza o termina esa cantidad de filas antes o después de la fila actual. En el modo GROUPS, el offset es un entero que indica que el marco comienza o termina esa cantidad de grupos de pares antes o después del grupo de pares de la fila actual, donde un grupo de pares es un grupo de filas que son equivalentes según la cláusula ORDER BY de la ventana. En el modo RANGE, el uso de una opción offset requiere que haya exactamente una columna ORDER BY en la definición de la ventana. Entonces el marco contiene aquellas filas cuyo valor de columna de ordenamiento no es menor que (para PRECEDING) o mayor que (para FOLLOWING) el valor de columna de ordenamiento de la fila actual más/menos la expresión offset. En estos casos, el tipo de datos de la expresión offset depende del tipo de datos de la columna de ordenamiento. Para columnas de ordenamiento numéricas, normalmente es del mismo tipo que la columna de ordenamiento, pero para columnas de ordenamiento de fecha y hora (datetime) es un interval. En todos estos casos, el valor del offset debe ser no nulo y no negativo. Además, aunque el offset no tiene que ser una constante simple, no puede contener variables, funciones de agregación o funciones de ventana.

La opción frame_exclusion permite que las filas alrededor de la fila actual se excluyan del marco, incluso si se incluyeran de acuerdo con las opciones de inicio de marco y fin de marco. EXCLUDE CURRENT ROW excluye la fila actual del marco. EXCLUDE GROUP excluye la fila actual y sus pares de ordenamiento del marco. EXCLUDE TIES excluye cualquier par de la fila actual del marco, pero no la fila actual en sí. EXCLUDE NO OTHERS simplemente especifica explícitamente el comportamiento por defecto de no excluir la fila actual ni sus pares.

Ten en cuenta que el modo ROWS puede producir resultados impredecibles si el ordenamiento ORDER BY no ordena las filas de manera única. Los modos RANGE y GROUPS están diseñados para garantizar que las filas que son pares en el ordenamiento ORDER BY se traten de la misma manera: todas las filas de un grupo de pares determinado estarán en el marco o se excluirán de él.

El propósito de una cláusula WINDOW es especificar el comportamiento de las funciones de ventana que aparecen en la SELECT list o la cláusula ORDER BY de la consulta. Estas funciones pueden hacer referencia a las entradas de la cláusula WINDOW por su nombre en sus cláusulas OVER. Sin embargo, no es necesario hacer referencia a una entrada de la cláusula WINDOW en ningún lugar; si no se utiliza en la consulta, simplemente se ignora. Es posible utilizar funciones de ventana sin ninguna cláusula WINDOW en absoluto, ya que una llamada a una función de ventana puede especificar su definición de ventana directamente en su cláusula OVER. Sin embargo, la cláusula WINDOW ahorra tener que escribir de más cuando se necesita la misma definición de ventana para más de una función de ventana.

Actualmente, no se pueden especificar FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE y FOR KEY SHARE con WINDOW.

Las funciones de ventana se describen detalladamente en Section 3.5, Section 4.2.8 y Section 7.2.5.

Lista de SELECT

La lista de SELECT (entre las palabras clave SELECT y FROM) especifica las expresiones que forman las filas de salida de la sentencia SELECT. Las expresiones pueden hacer referencia (y normalmente lo hacen) a columnas calculadas en la cláusula FROM.

Al igual que en una tabla, cada columna de salida de un SELECT tiene un nombre. En un SELECT simple, este nombre solo se utiliza para etiquetar la columna para su visualización, pero cuando el SELECT es una subconsulta de una consulta más grande, la consulta más grande ve el nombre como el nombre de columna de la tabla virtual producida por la subconsulta. Para especificar el nombre que se utilizará para una columna de salida, escribe AS output_name después de la expresión de la columna. (Puedes omitir AS, pero solo si el nombre de salida deseado no coincide con ninguna palabra clave de PostgreSQL (ver Appendix C). Para protegerte de la posible adición futura de palabras clave, se recomienda que siempre escribas AS o encierres entre comillas dobles el nombre de salida). Si no especificas un nombre de columna, PostgreSQL elige uno automáticamente. Si la expresión de la columna es una referencia simple a una columna, el nombre elegido será el mismo que el nombre de esa columna. En casos más complejos, se puede utilizar el nombre de una función o tipo, o el sistema puede recurrir a un nombre generado como ?column?.

El nombre de una columna de salida se puede utilizar para hacer referencia al valor de la columna en las cláusulas ORDER BY y GROUP BY, pero no en las cláusulas WHERE o HAVING; allí debes escribir la expresión completa en su lugar.

En lugar de una expresión, se puede escribir * en la lista de salida como una abreviatura para todas las columnas de las filas seleccionadas. También puedes escribir table_name.* como una abreviatura para las columnas que provienen únicamente de esa tabla. En estos casos, no es posible especificar nuevos nombres con AS; los nombres de las columnas de salida serán los mismos que los nombres de las columnas de la tabla.

Según el estándar SQL, las expresiones de la lista de salida deben calcularse antes de aplicar DISTINCT, ORDER BY o LIMIT. Esto es obviamente necesario al usar DISTINCT, ya que de lo contrario no estaría claro qué valores se están haciendo distintos. Sin embargo, en muchos casos es conveniente si las expresiones de salida se calculan después de ORDER BY y LIMIT; particularmente si la lista de salida contiene funciones volátiles o costosas. Con ese comportamiento, el orden de evaluación de las funciones es más intuitivo y no habrá evaluaciones correspondientes a filas que nunca aparecen en la salida. PostgreSQL evaluará de manera efectiva las expresiones de salida después de ordenar y limitar, siempre y cuando esas expresiones no estén referenciadas en DISTINCT, ORDER BY o GROUP BY. (Como contraejemplo, SELECT f(x) FROM tab ORDER BY 1 claramente debe evaluar f(x) antes de ordenar). Las expresiones de salida que contienen funciones que devuelven conjuntos se evalúan de manera efectiva después de ordenar y antes de limitar, de modo que LIMIT actuará para cortar la salida de una función que devuelve un conjunto.

Note

Las versiones de PostgreSQL anteriores a la 9.6 no ofrecían ninguna garantía sobre el momento de la evaluación de las expresiones de salida frente a la ordenación y la limitación; dependía de la forma del plan de consulta elegido.

Cláusula DISTINCT

Si se especifica SELECT DISTINCT, se eliminan todas las filas duplicadas del conjunto de resultados (se mantiene una fila de cada grupo de duplicados). SELECT ALL especifica lo contrario: se mantienen todas las filas; ese es el comportamiento por defecto.

SELECT DISTINCT ON ( expression [, ...] ) mantiene solo la primera fila de cada conjunto de filas donde las expresiones dadas se evalúan como iguales. Las expresiones de DISTINCT ON se interpretan utilizando las mismas reglas que para ORDER BY (ver arriba). Ten en cuenta que la primera fila de cada conjunto es impredecible a menos que se utilice ORDER BY para garantizar que la fila deseada aparezca primero. Por ejemplo:

SELECT DISTINCT ON (location) location, time, report
    FROM weather_reports
    ORDER BY location, time DESC;

recupera el reporte meteorológico más reciente para cada ubicación. Pero si no hubiéramos usado ORDER BY para forzar el orden descendente de los valores de tiempo para cada ubicación, habríamos obtenido un reporte de un tiempo impredecible para cada ubicación.

La(s) expresión(es) DISTINCT ON deben coincidir con la(s) expresión(es) ORDER BY más a la izquierda. La cláusula ORDER BY normalmente contendrá expresión(es) adicional(es) que determinan la precedencia deseada de las filas dentro de cada grupo de DISTINCT ON.

Actualmente, no se pueden especificar FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE y FOR KEY SHARE con DISTINCT.

Cláusula UNION

La cláusula UNION tiene esta forma general:

select_statement UNION [ ALL | DISTINCT ] select_statement

select_statement es cualquier sentencia SELECT sin una cláusula ORDER BY, LIMIT, FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE o FOR KEY SHARE. (ORDER BY y LIMIT se pueden adjuntar a una subexpresión si está encerrada entre paréntesis. Sin paréntesis, se considerará que estas cláusulas se aplican al resultado de la UNION, no a su expresión de entrada del lado derecho).

El operador UNION calcula la unión de conjuntos de las filas devueltas por las sentencias SELECT involucradas. Una fila está en la unión de conjuntos de dos conjuntos de resultados si aparece en al menos uno de los conjuntos de resultados. Las dos sentencias SELECT que representan los operandos directos de la UNION deben producir el mismo número de columnas, y las columnas correspondientes deben ser de tipos de datos compatibles.

El resultado de UNION no contiene filas duplicadas a menos que se especifique la opción ALL. ALL evita la eliminación de duplicados. (Por lo tanto, UNION ALL suele ser significativamente más rápido que UNION; usa ALL cuando puedas). Se puede escribir DISTINCT para especificar explícitamente el comportamiento por defecto de eliminar las filas duplicadas.

Los operadores UNION múltiples en la misma sentencia SELECT se evalúan de izquierda a derecha, a menos que se indique lo contrario mediante paréntesis.

Actualmente, no se pueden especificar FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE ni FOR KEY SHARE ni para un resultado de UNION ni para ninguna entrada de una UNION.

Cláusula INTERSECT

La cláusula INTERSECT tiene esta forma general:

select_statement INTERSECT [ ALL | DISTINCT ] select_statement

select_statement es cualquier sentencia SELECT sin una cláusula ORDER BY, LIMIT, FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE o FOR KEY SHARE.

El operador INTERSECT calcula la intersección de conjuntos de las filas devueltas por las sentencias SELECT involucradas. Una fila está en la intersección de dos conjuntos de resultados si aparece en ambos conjuntos de resultados.

El resultado de INTERSECT no contiene filas duplicadas a menos que se especifique la opción ALL. Con ALL, una fila que tiene m duplicados en la tabla izquierda y n duplicados en la tabla derecha aparecerá min(m,n) veces en el conjunto de resultados. Se puede escribir DISTINCT para especificar explícitamente el comportamiento por defecto de eliminar las filas duplicadas.

Los operadores INTERSECT múltiples en la misma sentencia SELECT se evalúan de izquierda a derecha, a menos que los paréntesis dicten lo contrario. INTERSECT se asocia con mayor prioridad que UNION. Es decir, A UNION B INTERSECT C se leerá como A UNION (B INTERSECT C).

Actualmente, no se pueden especificar FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE ni FOR KEY SHARE ni para un resultado de INTERSECT ni para ninguna entrada de un INTERSECT.

Cláusula EXCEPT

La cláusula EXCEPT tiene esta forma general:

select_statement EXCEPT [ ALL | DISTINCT ] select_statement

select_statement es cualquier sentencia SELECT sin una cláusula ORDER BY, LIMIT, FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE o FOR KEY SHARE.

El operador EXCEPT calcula el conjunto de filas que están en el resultado de la sentencia SELECT izquierda pero no en el resultado de la derecha.

El resultado de EXCEPT no contiene filas duplicadas a menos que se especifique la opción ALL. Con ALL, una fila que tiene m duplicados en la tabla izquierda y n duplicados en la tabla derecha aparecerá max(m-n,0) times en el conjunto de resultados. Se puede escribir DISTINCT para especificar explícitamente el comportamiento por defecto de eliminar las filas duplicadas.

Los operadores EXCEPT múltiples en la misma sentencia SELECT se evalúan de izquierda a derecha, a menos que los paréntesis dicten lo contrario. EXCEPT se asocia al mismo nivel que UNION.

Actualmente, no se pueden especificar FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE ni FOR KEY SHARE ni para un resultado de EXCEPT ni para ninguna entrada de un EXCEPT.

Cláusula ORDER BY

La cláusula opcional ORDER BY tiene esta forma general:

ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...]

La cláusula ORDER BY hace que las filas del resultado se ordenen según las expresiones especificadas. Si dos filas son iguales según la expresión más a la izquierda, se comparan según la siguiente expresión y así sucesivamente. Si son iguales según todas las expresiones especificadas, se devuelven en un orden que depende de la implementación.

Cada expression puede ser el nombre o número ordinal de una columna de salida (elemento de la lista de SELECT), o puede ser una expresión arbitraria formada a partir de los valores de las columnas de entrada.

El número ordinal se refiere a la posición ordinal (de izquierda a derecha) de la columna de salida. Esta característica permite definir un ordenamiento sobre la base de una columna que no tiene un nombre único. Esto nunca es absolutamente necesario porque siempre es posible asignar un nombre a una columna de salida utilizando la cláusula AS.

También es posible utilizar expresiones arbitrarias en la cláusula ORDER BY, incluyendo columnas que no aparecen en la lista de salida de SELECT. Por lo tanto, la siguiente sentencia es válida:

SELECT name FROM distributors ORDER BY code;

Una limitación de esta característica es que una cláusula ORDER BY que se aplica al resultado de una cláusula UNION, INTERSECT o EXCEPT solo puede especificar el nombre o número de una columna de salida, no una expresión.

Si una expresión ORDER BY es un nombre simple que coincide tanto con el nombre de una columna de salida como con el de una columna de entrada, ORDER BY lo interpretará como el nombre de la columna de salida. Esto es lo contrario de la elección que tomará GROUP BY en la misma situación. Esta inconsistencia se hace para ser compatible con el estándar SQL.

Opcionalmente se puede añadir la palabra clave ASC (ascendente) o DESC (descendente) después de cualquier expresión en la cláusula ORDER BY. Si no se especifica, se asume ASC por defecto. Alternativamente, se puede especificar un nombre de operador de ordenamiento específico en la cláusula USING. Un operador de ordenamiento debe ser un miembro de menor o mayor de alguna familia de operadores de árbol B (B-tree). ASC suele ser equivalente a USING < y DESC suele ser equivalente a USING >. (Pero el creador de un tipo de datos definido por el usuario puede definir exactamente cuál es el orden de ordenamiento por defecto, y este podría corresponder a operadores con otros nombres).

Si se especifica NULLS LAST, los valores nulos se ordenan después de todos los valores no nulos; si se especifica NULLS FIRST, los valores nulos se ordenan antes de todos los valores no nulos. Si no se especifica ninguno, el comportamiento por defecto es NULLS LAST cuando se especifica o implícita ASC, y NULLS FIRST cuando se especifica DESC (por lo tanto, el comportamiento por defecto es actuar como si los nulos fueran mayores que los no nulos). Cuando se especifica USING, el orden por defecto de los nulos depende de si el operador es un operador de menor o mayor.

Ten en cuenta que las opciones de ordenamiento se aplican únicamente a la expresión a la que siguen; por ejemplo, ORDER BY x, y DESC no significa lo mismo que ORDER BY x DESC, y DESC.

Los datos de cadenas de caracteres se ordenan según la colación (collation) que se aplica a la columna que se está ordenando. Eso se puede anular si es necesario incluyendo una cláusula COLLATE en la expression, por ejemplo ORDER BY mycolumn COLLATE "en_US". Para obtener más información, consulta Section 4.2.10 and Section 23.2.

Cláusula LIMIT

La cláusula LIMIT consta de dos subcláusulas independientes:

LIMIT { count | ALL }
OFFSET start

El parámetro count especifica el número máximo de filas a devolver, mientras que start especifica el número de filas que se deben omitir antes de comenzar a devolver filas. Cuando se especifican ambos, se omiten las filas de start antes de comenzar a contar las filas de count a devolver.

Si la expresión count se evalúa como NULL, se trata como LIMIT ALL, es decir, sin límite. Si start se evalúa como NULL, se trata de la misma manera que OFFSET 0.

SQL:2008 introdujo una sintaxis diferente para lograr el mismo resultado, que PostgreSQL también soporta. Es:

OFFSET start { ROW | ROWS }
FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } { ONLY | WITH TIES }

En esta sintaxis, el estándar requiere que el valor de start o count sea una constante literal, un parámetro o un nombre de variable; como una extensión de PostgreSQL, se permiten otras expresiones, pero generalmente deberán estar encerradas entre paréntesis para evitar ambigüedades. Si se omite count en una cláusula FETCH, su valor por defecto es 1. La opción WITH TIES se utiliza para devolver cualquier fila adicional que empate por el último lugar en el conjunto de resultados según la cláusula ORDER BY; ORDER BY es obligatorio en este caso, y no se permite SKIP LOCKED. Las palabras ROW y ROWS, así como FIRST and NEXT, son palabras de adorno que no influyen en los efectos de estas cláusulas. Según el estándar, la cláusula OFFSET debe ir antes de la cláusula FETCH si ambas están presentes; pero PostgreSQL es más flexible y permite cualquier orden.

Al utilizar LIMIT, es una buena idea usar una cláusula ORDER BY que restrinja las filas del resultado a un orden único. De lo contrario, obtendrás un subconjunto impredecible de las filas de la consulta — podrías estar solicitando desde la décima hasta la vigésima fila, pero ¿la décima hasta la vigésima en qué orden? No conoces el orden a menos que especifiques ORDER BY.

El planificador de consultas tiene en cuenta LIMIT al generar un plan de consulta, por lo que es muy probable que obtengas diferentes planes (que producen diferentes órdenes de filas) dependiendo de lo que uses para LIMIT y OFFSET. Por lo tanto, el uso de diferentes valores de LIMIT/OFFSET para seleccionar diferentes subconjuntos de un resultado de consulta dará como resultado datos inconsistentes a menos que fuerces un orden de resultado predecible con ORDER BY. Esto no es un error; es una consecuencia inherente del hecho de que SQL no promete entregar los resultados de una consulta en ningún orden en particular a menos que se utilice ORDER BY para restringir el orden.

Incluso es posible que ejecuciones repetidas de la misma consulta LIMIT devuelvan subconjuntos de filas diferentes de una tabla, si no hay un ORDER BY para forzar la selección de un subconjunto determinista. Nuevamente, esto no es un error; el determinismo de los resultados simplemente no está garantizado en tal caso.

La cláusula de bloqueo (Locking Clause)

FOR UPDATE, FOR NO KEY UPDATE, FOR SHARE y FOR KEY SHARE son cláusulas de bloqueo (locking clauses); afectan el modo en que SELECT bloquea las filas a medida que se obtienen de la tabla.

La cláusula de bloqueo tiene la forma general

FOR lock_strength [ OF from_reference [, ...] ] [ NOWAIT | SKIP LOCKED ]

donde lock_strength puede ser uno de

UPDATE
NO KEY UPDATE
SHARE
KEY SHARE

from_reference debe ser un alias de tabla o un table_name no oculto referenciado en la cláusula FROM. Para obtener más información sobre cada modo de bloqueo a nivel de fila, consulta Section 13.3.2.

Para evitar que la operación espere a que otras transacciones se confirmen, usa la opción NOWAIT o SKIP LOCKED. Con NOWAIT, la sentencia informa un error, en lugar de esperar, si una fila seleccionada no se puede bloquear de inmediato. Con SKIP LOCKED, se omiten las filas seleccionadas que no se puedan bloquear de inmediato. Omitir las filas bloqueadas proporciona una vista inconsistente de los datos, por lo que esto no es adecuado para trabajos de propósito general, pero se puede usar para evitar la contención de bloqueos con múltiples consumidores que acceden a una tabla similar a una cola. Ten en cuenta que NOWAIT y SKIP LOCKED se aplican únicamente a los bloqueos a nivel de fila — el bloqueo a nivel de tabla ROW SHARE requerido se sigue adquiriendo de la manera habitual (ver Chapter 13). Puedes usar LOCK con la opción NOWAIT primero, si necesitas adquirir el bloqueo a nivel de tabla sin esperar.

Si se nombran tablas específicas en una cláusula de bloqueo, entonces solo se bloquean las filas provenientes de esas tablas; cualquier otra tabla utilizada en el SELECT simplemente se lee de la manera habitual. Una cláusula de bloqueo sin una lista de tablas afecta a todas las tablas utilizadas en la sentencia. Si una cláusula de bloqueo se aplica a una vista o subconsulta, afecta a todas las tablas utilizadas en la vista o subconsulta. Sin embargo, estas cláusulas no se aplican a las consultas WITH referenciadas por la consulta principal. Si deseas que ocurra un bloqueo de filas dentro de una consulta WITH, especifica una cláusula de bloqueo dentro de la consulta WITH.

Se pueden escribir múltiples cláusulas de bloqueo si es necesario especificar un comportamiento de bloqueo diferente para diferentes tablas. Si la misma tabla es mencionada (o afectada implícitamente) por más de una cláusula de bloqueo, entonces se procesa como si solo se hubiera especificado en la más fuerte. Del mismo modo, una tabla se procesa como NOWAIT si eso se especifica en alguna de las cláusulas que la afectan. De lo contrario, se procesa como SKIP LOCKED si eso se especifica en alguna de las cláusulas que la afectan.

Las cláusulas de bloqueo no se pueden utilizar en contextos donde las filas devueltas no puedan identificarse claramente con filas de tabla individuales; por ejemplo, no se pueden usar con agregación.

Cuando una cláusula de bloqueo aparece en el nivel superior de una consulta SELECT, las filas que se bloquean son exactamente aquellas que devuelve la consulta; en el caso de una consulta de unión (join), las filas bloqueadas son aquellas que contribuyen a las filas de unión devueltas. Además, se bloquearán las filas que cumplan con las condiciones de la consulta a partir de la instantánea (snapshot) de la consulta, aunque no se devolverán si se actualizaron después de la instantánea y ya no cumplen con las condiciones de la consulta. Si se utiliza LIMIT, el bloqueo se detiene una vez que se han devuelto suficientes filas para cumplir con el límite (pero ten en cuenta que las filas omitidas por OFFSET se bloquearán). Del mismo modo, si se utiliza una cláusula de bloqueo en la consulta de un cursor, solo se bloquearán las filas realmente recuperadas (fetched) o sobrepasadas por el cursor.

Cuando una cláusula de bloqueo aparece en un sub-SELECT, las filas bloqueadas son aquellas devueltas a la consulta externa por la subconsulta. Esto podría involucrar menos filas de las que sugeriría la inspección de la subconsulta por sí sola, ya que las condiciones de la consulta externa podrían usarse para optimizar la ejecución de la subconsulta. Por ejemplo,

SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5;

bloqueará únicamente las filas que tengan col1 = 5, aunque esa condición no esté textualmente dentro de la subconsulta.

Las versiones anteriores no preservaban un bloqueo que es promovido por un punto de salvaguarda (savepoint) posterior. Por ejemplo, este código:

BEGIN;
SELECT * FROM mytable WHERE key = 1 FOR UPDATE;
SAVEPOINT s;
UPDATE mytable SET ... WHERE key = 1;
ROLLBACK TO s;

fallaría al preservar el bloqueo FOR UPDATE después del ROLLBACK TO. Esto se ha solucionado en la versión 9.3.

Caution

Es posible que un comando SELECT que se ejecuta en el nivel de aislamiento de transacción READ COMMITTED y que utiliza ORDER BY y una cláusula de bloqueo devuelva filas fuera de orden. Esto se debe a que ORDER BY se aplica primero. El comando ordena el resultado, pero luego podría bloquearse intentando obtener un bloqueo en una o más de las filas. Una vez que el SELECT se desbloquea, algunos de los valores de las columnas de ordenamiento podrían haber sido modificados, lo que hace que esas filas parezcan estar fuera de orden (aunque están en orden en términos de los valores de las columnas originales). Esto se puede solucionar si es necesario colocando la cláusula FOR UPDATE/SHARE en una subconsulta, por ejemplo:

SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1;

Ten en cuenta que esto dará como resultado el bloqueo de todas las filas de mytable, mientras que FOR UPDATE en el nivel superior bloquearía solo las filas realmente devueltas. Esto puede marcar una diferencia significativa en el rendimiento, particularmente si el ORDER BY se combina con LIMIT u otras restricciones. Por lo tanto, esta técnica se recomienda solo si se esperan actualizaciones concurrentes de las columnas de ordenamiento y se requiere un resultado estrictamente ordenado.

En el nivel de aislamiento de transacción REPEATABLE READ o SERIALIZABLE esto provocaría un fallo de serialización (con un SQLSTATE de '40001'), por lo que no hay posibilidad de recibir filas fuera de orden bajo estos niveles de aislamiento.

Comando TABLE

El comando

TABLE name

es equivalente a

SELECT * FROM name

Se puede usar como un comando de nivel superior o como una variante de sintaxis para ahorrar espacio en partes de consultas complejas. Solo las cláusulas de bloqueo WITH, UNION, INTERSECT, EXCEPT, ORDER BY, LIMIT, OFFSET, FETCH y FOR se pueden usar con TABLE; la cláusula WHERE y cualquier forma de agregación no se pueden utilizar.

Ejemplos

Para unir la tabla films con la tabla distributors:

SELECT f.title, f.did, d.name, f.date_prod, f.kind
    FROM distributors d JOIN films f USING (did);

       title       | did |     name     | date_prod  |   kind
-------------------+-----+--------------+------------+----------
 The Third Man     | 101 | British Lion | 1949-12-23 | Drama
 The African Queen | 101 | British Lion | 1951-08-11 | Romantic
 ...

Para sumar la columna len de todas las películas y agrupar los resultados por kind:

SELECT kind, sum(len) AS total FROM films GROUP BY kind;

   kind   | total
----------+-------
 Action   | 07:34
 Comedy   | 02:58
 Drama    | 14:28
 Musical  | 06:42
 Romantic | 04:38

Para sumar la columna len de todas las películas, agrupar los resultados por kind y mostrar aquellos totales de grupo que sean menores de 5 horas:

SELECT kind, sum(len) AS total
    FROM films
    GROUP BY kind
    HAVING sum(len) < interval '5 hours';

   kind   | total
----------+-------
 Comedy   | 02:58
 Romantic | 04:38

Los siguientes dos ejemplos son formas idénticas de ordenar los resultados individuales según el contenido de la segunda columna (name):

SELECT * FROM distributors ORDER BY name;
SELECT * FROM distributors ORDER BY 2;

 did |       name
-----+------------------
 109 | 20th Century Fox
 110 | Bavaria Atelier
 101 | British Lion
 107 | Columbia
 102 | Jean Luc Godard
 113 | Luso films
 104 | Mosfilm
 103 | Paramount
 106 | Toho
 105 | United Artists
 111 | Walt Disney
 112 | Warner Bros.
 108 | Westward

El siguiente ejemplo muestra cómo obtener la unión de las tablas distributors y actors, restringiendo los resultados a aquellos que comienzan con la letra W en cada tabla. Solo se desean filas distintas, por lo que se omite la palabra clave ALL.

distributors:               actors:
 did |     name              id |     name
-----+--------------        ----+----------------
 108 | Westward               1 | Woody Allen
 111 | Walt Disney            2 | Warren Beatty
 112 | Warner Bros.           3 | Walter Matthau
 ...                         ...

SELECT distributors.name
    FROM distributors
    WHERE distributors.name LIKE 'W%'
UNION
SELECT actors.name
    FROM actors
    WHERE actors.name LIKE 'W%';

      name
----------------
 Walt Disney
 Walter Matthau
 Warner Bros.
 Warren Beatty
 Westward
 Woody Allen

Este ejemplo muestra cómo utilizar una función en la cláusula FROM, tanto con como sin una lista de definición de columnas:

CREATE FUNCTION distributors(int) RETURNS SETOF distributors AS $$
    SELECT * FROM distributors WHERE did = $1;
$$ LANGUAGE SQL;

SELECT * FROM distributors(111);
 did |    name
-----+-------------
 111 | Walt Disney

CREATE FUNCTION distributors_2(int) RETURNS SETOF record AS $$
    SELECT * FROM distributors WHERE did = $1;
$$ LANGUAGE SQL;

SELECT * FROM distributors_2(111) AS (f1 int, f2 text);
 f1  |     f2
-----+-------------
 111 | Walt Disney

Aquí tienes un ejemplo de una función con una columna de ordinalidad añadida:

SELECT * FROM unnest(ARRAY['a','b','c','d','e','f']) WITH ORDINALITY;
 unnest | ordinality
--------+----------
 a      |        1
 b      |        2
 c      |        3
 d      |        4
 e      |        5
 f      |        6
(6 rows)

Este ejemplo muestra cómo utilizar una cláusula WITH simple:

WITH t AS (
    SELECT random() as x FROM generate_series(1, 3)
  )
SELECT * FROM t
UNION ALL
SELECT * FROM t;
         x
--------------------
  0.534150459803641
  0.520092216785997
 0.0735620250925422
  0.534150459803641
  0.520092216785997
 0.0735620250925422

Ten en cuenta que la consulta WITH se evaluó solo una vez, por lo que obtuvimos dos conjuntos de los mismos tres valores aleatorios.

Este ejemplo utiliza WITH RECURSIVE para encontrar todos los subordinados (directos o indirectos) de la empleada Mary, y su nivel de indirecta, a partir de una tabla que muestra solo los subordinados directos:

WITH RECURSIVE employee_recursive(distance, employee_name, manager_name) AS (
    SELECT 1, employee_name, manager_name
    FROM employee
    WHERE manager_name = 'Mary'
  UNION ALL
    SELECT er.distance + 1, e.employee_name, e.manager_name
    FROM employee_recursive er, employee e
    WHERE er.employee_name = e.manager_name
  )
SELECT distance, employee_name FROM employee_recursive;

Ten en cuenta la forma típica de las consultas recursivas: una condición inicial, seguida de UNION, seguida de la parte recursiva de la consulta. Asegúrate de que la parte recursiva de la consulta eventualmente no devuelva tuplas, o de lo contrario la consulta entrará en un bucle infinito. (Consulta Section 7.8 para ver más ejemplos).

Este ejemplo utiliza LATERAL para aplicar una función que devuelve un conjunto get_product_names() para cada fila de la tabla manufacturers:

SELECT m.name AS mname, pname
FROM manufacturers m, LATERAL get_product_names(m.id) pname;

Los fabricantes que no tienen productos actualmente no aparecerían en el resultado, ya que se trata de una unión interna (inner join). Si quisiéramos incluir los nombres de dichos fabricantes en el resultado, podríamos hacer lo siguiente:

SELECT m.name AS mname, pname
FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true;

Compatibilidad

Por supuesto, la sentencia SELECT es compatible con el estándar SQL. Pero existen algunas extensiones y algunas características ausentes.

Cláusulas FROM omitidas

PostgreSQL permite omitir la cláusula FROM. Esto tiene un uso sencillo para calcular los resultados de expresiones simples:

SELECT 2+2;

 ?column?
----------
        4

Algunas otras bases de datos SQL no pueden hacer esto a menos que introduzcan una tabla ficticia de una sola fila desde la cual realizar el SELECT.

Listas de SELECT vacías

La lista de expresiones de salida después de SELECT puede estar vacía, produciendo una tabla de resultados de cero columnas. Esta no es una sintaxis válida según el estándar SQL. PostgreSQL lo permite para ser consistente con la posibilidad de permitir tablas de cero columnas. Sin embargo, no se permite una lista vacía cuando se utiliza DISTINCT.

Omisión de la palabra clave AS

En el estándar SQL, la palabra clave opcional AS se puede omitir antes del nombre de una columna de salida siempre que el nuevo nombre de columna sea un nombre de columna válido (es decir, que no coincida con ninguna palabra clave reservada). PostgreSQL es ligeramente más restrictivo: se requiere AS si el nuevo nombre de la columna coincide con cualquier palabra clave, reservada o no. La práctica recomendada es usar AS o escribir entre comillas dobles los nombres de las columnas de salida, para evitar cualquier posible conflicto con futuras adiciones de palabras clave.

En los elementos de FROM, tanto el estándar como PostgreSQL permiten omitir AS antes de un alias que sea una palabra clave no reservada. Pero esto no es práctico para los nombres de las columnas de salida debido a ambigüedades sintácticas.

Omisión de alias de sub-SELECT en FROM

Según el estándar SQL, un sub-SELECT en la lista FROM debe tener un alias. En PostgreSQL, este alias se puede omitir.

ONLY y herencia

El estándar SQL requiere paréntesis alrededor del nombre de la tabla al escribir ONLY, por ejemplo SELECT * FROM ONLY (tab1), ONLY (tab2) WHERE .... PostgreSQL considera que estos paréntesis son opcionales.

PostgreSQL permite escribir un * al final para especificar explícitamente el comportamiento no-ONLY de incluir las tablas hijas. El estándar no permite esto.

(Estos puntos se aplican por igual a todos los comandos SQL que soportan la opción ONLY).

Restricciones de la cláusula TABLESAMPLE

La cláusula TABLESAMPLE se acepta actualmente solo en tablas normales y vistas materializadas. Según el estándar SQL debería ser posible aplicarla a cualquier elemento de FROM.

Llamadas a funciones en FROM

PostgreSQL permite escribir una llamada a una función directamente como un miembro de la lista FROM. En el estándar SQL sería necesario envolver dicha llamada a función en un sub-SELECT; es decir, la sintaxis FROM func(...) alias es aproximadamente equivalente a FROM LATERAL (SELECT func(...)) alias. Ten en cuenta que LATERAL se considera implícito; esto se debe a que el estándar requiere la semántica de LATERAL para un elemento UNNEST() en FROM. PostgreSQL trata a UNNEST() de la misma manera que a otras funciones que devuelven conjuntos.

Espacio de nombres disponible para GROUP BY y ORDER BY

En el estándar SQL-92, una cláusula ORDER BY solo puede usar nombres o números de columnas de salida, mientras que una cláusula GROUP BY solo puede usar expresiones basadas en nombres de columnas de entrada. PostgreSQL extiende cada una de estas cláusulas para permitir también la otra opción (pero utiliza la interpretación del estándar si hay ambigüedad). PostgreSQL también permite que ambas cláusulas especifiquen expresiones arbitrarias. Ten en cuenta que los nombres que aparecen en una expresión siempre se tomarán como nombres de columnas de entrada, no como nombres de columnas de salida.

SQL:1999 y posteriores utilizan una definición ligeramente diferente que no es completamente compatible hacia adelante con SQL-92. Sin embargo, en la mayoría de los casos PostgreSQL interpretará una expresión de ORDER BY o GROUP BY de la misma manera que lo hace SQL:1999.

Dependencias funcionales

PostgreSQL reconoce la dependencia funcional (permitiendo omitir columnas de GROUP BY) solo cuando la clave primaria de una tabla está incluida en la lista de GROUP BY. El estándar SQL especifica condiciones adicionales que deberían ser reconocidas.

LIMIT y OFFSET

Las cláusulas LIMIT y OFFSET son una sintaxis específica de PostgreSQL, también utilizada por MySQL. El estándar SQL:2008 ha introducido las cláusulas OFFSET ... FETCH {FIRST|NEXT} ... para la misma funcionalidad, como se muestra arriba en LIMIT Clause. Esta sintaxis también es utilizada por IBM DB2. (Las aplicaciones escritas para Oracle frecuentemente utilizan una solución alternativa que involucra la columna rownum generada automáticamente, la cual no está disponible en PostgreSQL, para implementar los efectos de estas cláusulas).

FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE, FOR KEY SHARE

Aunque FOR UPDATE appears en el estándar SQL, el estándar lo permite solo como una opción de DECLARE CURSOR. PostgreSQL lo permite en cualquier consulta SELECT así como en sub-SELECTs, pero esto es una extensión. Las variantes FOR NO KEY UPDATE, FOR SHARE y FOR KEY SHARE, así como las opciones NOWAIT y SKIP LOCKED, no aparecen en el estándar.

Sentencias de modificación de datos en WITH

PostgreSQL permite utilizar INSERT, UPDATE, DELETE y MERGE como consultas WITH. Esto no se encuentra en el estándar SQL.

Cláusulas no estándar

DISTINCT ON ( ... ) es una extensión del estándar SQL.

ROWS FROM( ... ) es una extensión del estándar SQL.

Las opciones MATERIALIZED y NOT MATERIALIZED de WITH son extensiones del estándar SQL.