SELECT, TABLE, WITH — recuperar filas de una tabla o vista
[ WITH [ RECURSIVE ]with_query[, ...] ] SELECT [ ALL | DISTINCT [ ON (expression[, ...] ) ] ] [ { * |expression[ [ AS ]output_name] } [, ...] ] [ FROMfrom_item[, ...] ] [ WHEREcondition] [ GROUP BY [ ALL | DISTINCT ]grouping_element[, ...] ] [ HAVINGcondition] [ WINDOWwindow_nameAS (window_definition) [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ]select] [ ORDER BYexpression[ ASC | DESC | USINGoperator] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT {count| ALL } ] [ OFFSETstart[ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [count] { ROW | ROWS } { ONLY | WITH TIES } ] [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OFfrom_reference[, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ] dondefrom_itempuede ser uno de: [ ONLY ]table_name[ * ] [ [ AS ]alias[ (column_alias[, ...] ) ] ] [ TABLESAMPLEsampling_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_itemjoin_typefrom_item{ ONjoin_condition| USING (join_column[, ...] ) [ ASjoin_using_alias] }from_itemNATURALjoin_typefrom_itemfrom_itemCROSS JOINfrom_itemygrouping_elementpuede ser uno de: ( )expression(expression[, ...] ) ROLLUP ( {expression| (expression[, ...] ) } [, ...] ) CUBE ( {expression| (expression[, ...] ) } [, ...] ) GROUPING SETS (grouping_element[, ...] ) ywith_queryes:with_query_name[ (column_name[, ...] ) ] AS [ [ NOT ] MATERIALIZED ] (select|values|insert|update|delete|merge) [ SEARCH { BREADTH | DEPTH } FIRST BYcolumn_name[, ...] SETsearch_seq_col_name] [ CYCLEcolumn_name[, ...] SETcycle_mark_col_name[ TOcycle_mark_valueDEFAULTcycle_mark_default] USINGcycle_path_col_name] TABLE [ ONLY ]table_name[ * ]
SELECT recupera filas de cero o más tablas.
El procesamiento general de SELECT es el siguiente:
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).
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).
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).
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.
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).
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).
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).
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).
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).
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).
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_termUNION [ 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.
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 ( . La lista de definiciones de columnas debe coincidir con el
número y los tipos reales de las columnas devueltas por la función.
column_name data_type [, ...
])
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_typeUno 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_conditionUSING (
o join_column [, ...])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_conditionjoin_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
es sintácticamente válida, en realidad no está permitido que X RIGHT JOIN LATERAL YY haga
referencia a X.
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.
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.
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.
WINDOW
La cláusula opcional WINDOW tiene la forma general
WINDOWwindow_nameAS (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 BYexpression[, ...] ] [ ORDER BYexpression[ ASC | DESC | USINGoperator] [ 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 PRECEDINGoffsetPRECEDING CURRENT ROWoffsetFOLLOWING 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 no está permitido.
offset
PRECEDING
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.
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 como una abreviatura para
las columnas que provienen únicamente de esa tabla. En estos casos, no es posible
especificar nuevos nombres con table_name.*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.
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.
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 (
mantiene solo la primera fila de cada conjunto de filas donde las expresiones
dadas se evalúan como iguales. Las expresiones de expression [, ...] )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.
UNION
La cláusula UNION tiene esta forma general:
select_statementUNION [ 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.
INTERSECT
La cláusula INTERSECT tiene esta forma general:
select_statementINTERSECT [ 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.
EXCEPT
La cláusula EXCEPT tiene esta forma general:
select_statementEXCEPT [ 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.
ORDER BY
La cláusula opcional ORDER BY tiene esta forma general:
ORDER BYexpression[ ASC | DESC | USINGoperator] [ 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.
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:
OFFSETstart{ 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.
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
FORlock_strength[ OFfrom_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.
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.
TABLEEl 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.
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;
Por supuesto, la sentencia SELECT es compatible
con el estándar SQL. Pero existen algunas extensiones y algunas
características ausentes.
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.
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.
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.
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).
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.
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
es aproximadamente equivalente a
func(...) aliasFROM LATERAL (SELECT .
Ten en cuenta que func(...)) aliasLATERAL 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.
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.
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.
WITH
PostgreSQL permite utilizar INSERT,
UPDATE, DELETE y
MERGE como consultas WITH. Esto no se
encuentra en el estándar SQL.
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.