SELECT, TABLE, WITH — recupera linhas de uma tabela ou visão
[ WITH [ RECURSIVE ]consulta_WITH[, ...] ] SELECT [ ALL | DISTINCT [ ON (expressão[, ...] ) ] ] [ { * |expressão[ [ AS ]nome_de_saída] } [, ...] ] [ FROMitem_FROM[, ...] ] [ WHEREcondição] [ GROUP BY [ ALL | DISTINCT ]elemento_de_agrupamento[, ...] ] [ HAVINGcondição] [ WINDOWnome_da_janelaAS (definição_da_janela) [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ]seleção] [ ORDER BYexpressão[ ASC | DESC | USINGoperador] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT {contador| ALL } ] [ OFFSETinício[ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [contador] { ROW | ROWS } { ONLY | WITH TIES } ] [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OFreferência_FROM[, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ] ondeitem_FROMpode ser um entre: [ ONLY ]nome_da_tabela[ * ] [ [ AS ]alias[ (alias_de_coluna[, ...] ) ] ] [ TABLESAMPLEmétodo_de_amostragem(argumento[, ...] ) [ REPEATABLE (semente) ] ] [ LATERAL ] (seleção) [ [ AS ]alias[ (alias_de_coluna[, ...] ) ] ]nome_da_consulta_WITH[ [ AS ]alias[ (alias_de_coluna[, ...] ) ] ] [ LATERAL ]nome_da_função( [argumento[, ...] ] ) [ WITH ORDINALITY ] [ [ AS ]alias[ (alias_de_coluna[, ...] ) ] ] [ LATERAL ]nome_da_função( [argumento[, ...] ] ) [ AS ]alias(definição_de_coluna[, ...] ) [ LATERAL ]nome_da_função( [argumento[, ...] ] ) AS (definição_de_coluna[, ...] ) [ LATERAL ] ROWS FROM (nome_da_função( [argumento[, ...] ] ) [ AS (definição_de_coluna[, ...] ) ] [, ...] ) [ WITH ORDINALITY ] [ [ AS ]alias[ (alias_de_coluna[, ...] ) ] ]item_FROMtipo_de_junçãoitem_FROM{ ONcondição_de_junção| USING (coluna_de_junção[, ...] ) [ ASjunção_usando_alias] }item_FROMNATURALtipo_de_junçãoitem_FROMitem_FROMCROSS JOINitem_FROMeelemento_de_agrupamentopode ser um entre: ( )expressão(expressão[, ...] ) ROLLUP ( {expressão| (expressão[, ...] ) } [, ...] ) CUBE ( {expressão| (expressão[, ...] ) } [, ...] ) GROUPING SETS (elemento_de_agrupamento[, ...] ) econsulta_WITHé:nome_da_consulta_WITH[ (nome_da_coluna[, ...] ) ] AS [ [ NOT ] MATERIALIZED ] (seleção|values|insert|update|delete|merge) [ SEARCH { BREADTH | DEPTH } FIRST BYnome_da_coluna[, ...] SETsearch_seq_col_name] [ CYCLEnome_da_coluna[, ...] SETcycle_mark_col_name[ TOcycle_mark_valueDEFAULTcycle_mark_default] USINGcycle_path_col_name] TABLE [ ONLY ]nome_da_tabela[ * ]
O comando SELECT recupera linhas de zero ou mais tabelas.
O processamento geral do comando SELECT é o seguinte:
Todas as consultas na lista da cláusula WITH
são computadas.
Elas servem efetivamente como tabelas temporárias que podem ser
referenciadas na lista da cláusula FROM.
Uma consulta WITH referenciada mais de
uma vez na lista da cláusula FROM é computada
apenas uma vez, a menos que seja especificado de outra forma pela
cláusula NOT MATERIALIZED.
(Veja a Cláusula WITH abaixo.)
Todos os elementos na lista da cláusula FROM
são computados.
(Cada elemento na lista da cláusula FROM
é uma tabela real ou virtual.)
Se for especificado mais de um elemento na lista da cláusula
FROM, eles serão juntados entre si.
(Veja a Cláusula FROM abaixo.)
Se for especificada a cláusula WHERE, todas
as linhas que não atenderem à condição serão excluídas da saída.
(Veja a Cláusula WHERE abaixo.)
Se for especificada a cláusula GROUP BY,
ou havendo chamada a funções de agregação, a saída será
combinada em grupos de linhas que correspondem a um ou mais
valores, e serão calculados os resultados das funções de agregação.
Se estiver presente a cláusula HAVING, serão
eliminados os grupos que não atendem a condição especificada.
(Veja a Cláusula GROUP BY e a
Cláusula HAVING abaixo.)
Embora as colunas de saída da consulta sejam nominalmente
calculadas na próxima etapa, elas também podem ser referenciadas
(por nome ou por número ordinal) na cláusula
GROUP BY.
As linhas de saída reais são calculadas usando as expressões de
saída do comando SELECT para cada linha ou
grupo de linhas selecionado.
(Veja a Lista SELECT abaixo.)
SELECT DISTINCT remove do resultado as linhas
duplicadas.
SELECT DISTINCT ON remove as linhas que
correspondem a todas as expressões especificadas.
SELECT ALL (o padrão) retorna todas as linhas
candidatas, incluindo as duplicadas.
(Veja a Cláusula DISTINCT abaixo.)
Usando os operadores UNION,
INTERSECT, e EXCEPT,
podem ser combinadas as saídas de mais de um comando
SELECT para formar um único conjunto de
resultados.
O operador UNION retorna todas as linhas que
estão presentes em um ou nos dois conjuntos de resultados.
O operador INTERSECT retorna todas as linhas
que estão presentes nos dois conjuntos de resultados.
O operador EXCEPT retorna as linhas que estão
no primeiro conjunto de resultados, mas não no segundo.
Em todos estes três casos as linhas duplicadas são eliminadas,
a menos que seja especificado ALL.
A palavra ruído DISTINCT pode ser adicionada
para especificar explicitamente a eliminação das linhas duplicadas.
Note que DISTINCT é o comportamento padrão
aqui, embora ALL seja o comportamento padrão
para o próprio comando SELECT.
(Veja a Cláusula UNION, a Cláusula INTERSECT
e a Cláusula EXCEPT abaixo.)
Se for especificada a cláusula ORDER BY,
as linhas retornadas serão classificadas na ordem especificada.
Se a cláusula ORDER BY não estiver presente,
as linhas irão retornar na ordem que o sistema achar mais rápida
de produzir.
(Veja a Cláusula ORDER BY abaixo.)
Se for especificada a cláusula LIMIT
(ou FETCH FIRST), ou OFFSET,
o comando SELECT irá retornar apenas um
subconjunto das linhas de resultado.
(Veja a Cláusula LIMIT abaixo.)
Se for especificado FOR UPDATE,
FOR NO KEY UPDATE, FOR SHARE,
ou FOR KEY SHARE,
o comando SELECT irá bloquear as linhas
selecionadas contra atualizações simultâneas.
(Veja Cláusula de bloqueio abaixo.)
É necessário possuir o privilégio SELECT em cada
coluna usada em um comando SELECT.
O uso de FOR NO KEY UPDATE,
FOR UPDATE, FOR SHARE, ou
FOR KEY SHARE, também requer o privilégio de
UPDATE
(para pelo menos uma coluna de cada tabela selecionada).
WITH
A cláusula WITH permite que se especifique
uma ou mais subconsultas, que podem ser referenciadas pelo nome
na consulta primária.
As subconsultas atuam efetivamente como tabelas ou visões
temporárias durante a consulta principal.
Cada subconsulta pode ser um comando SELECT,
TABLE, VALUES,
INSERT, UPDATE,
DELETE ou MERGE.
Ao escrever um comando de modificação de dados
(INSERT, UPDATE,
DELETE ou MERGE)
na cláusula WITH,
é comum incluir a cláusula RETURNING.
É a saída da cláusula RETURNING, e
não a tabela subjacente que o comando modifica,
que forma a tabela temporária lida pela consulta primária.
Se for omitida a cláusula RETURNING, o comando
ainda assim será executado, mas não produzirá saída, portanto não
poderá ser referenciado como uma tabela pela consulta primária.
Deve ser especificado um nome (sem qualificação de esquema) para
cada consulta da cláusula WITH.
Opcionalmente, pode ser especificada uma lista de nomes de colunas;
se for omitido, os nomes das colunas serão inferidos da subconsulta.
Se for especificado RECURSIVE, é permitido que
a subconsulta SELECT faça referência a si mesma
pelo nome.
Esta subconsulta deve ter o formato
termo_não_recursivoUNION [ ALL | DISTINCT ]termo_recursivo
onde a autorreferência recursiva deve aparecer no lado direito
do operador UNION.
É permitida apenas uma autorreferência recursiva por consulta.
Não há suporte para comandos de modificação de dados recursivos,
mas podem ser usados os resultados da consulta
SELECT recursiva em um comando de modificação
de dados.
Veja Consultas WITH (Expressões de tabela comuns) para obter um exemplo.
Outro efeito de RECURSIVE é que as consultas
WITH não precisam ser ordenadas: a consulta pode
referir-se a outra que esteja posteriormente na lista.
(Entretanto, referências circulares, ou recursão mútua, não estão
implementadas.)
Sem RECURSIVE, as consultas WITH
só podem referir-se a outras consultas WITH
que estão anteriormente na lista WITH.
Quando houver várias consultas na cláusula WITH,
RECURSIVE deve ser escrito apenas uma vez,
imediatamente após a cláusula WITH.
Isto se aplica a todas as consultas na cláusula WITH,
embora não afete as consultas que não usam recursão ou
referências diretas.
A cláusula opcional SEARCH computa uma
coluna de sequência de procura, que pode ser
usada para ordenar os resultados de uma consulta recursiva em ordem
de largura ou profundidade.
A lista de nomes de coluna fornecida especifica a chave de linha
que deve ser usada para controlar as linhas visitadas.
Uma coluna chamada search_seq_col_name
será adicionada à lista de colunas de resultados da consulta
WITH.
Esta coluna pode ser ordenada na consulta externa para obter a
respectiva ordenação.
Veja Ordem de procura para obter exemplos.
A cláusula opcional CYCLE é usada para detectar
ciclos em consultas recursivas.
A lista de nomes de coluna fornecida especifica a chave de linha
que deve ser usada para controlar as linhas visitadas.
Uma coluna chamada cycle_mark_col_name
será adicionada à lista de colunas de resultados da consulta
WITH.
Esta coluna será definida como cycle_mark_value
quando for detectado um ciclo, caso contrário, será
cycle_mark_default.
Além disso, o processamento da união recursiva será interrompido
quando for detectado um ciclo.
cycle_mark_value e
cycle_mark_default devem ser constantes,
e devem ser coercíveis para um tipo de dados comum, e o tipo de dados
deve ter um operador de desigualdade.
(O padrão SQL exige que sejam constantes booleanas,
ou cadeias de caracteres, mas o PostgreSQL
não exige isto.)
Por padrão, são usados TRUE e
FALSE (do tipo boolean).
Além disso, será adicionada uma coluna chamada
cycle_path_col_name à lista de colunas
de resultados da consulta WITH.
Esta coluna é usada internamente para rastrear as linhas visitadas.
Veja Detecção de ciclo para obter exemplos.
As cláusulas SEARCH e CYCLE
são válidas apenas para consultas WITH recursivas.
A consulta_WITH deve ser uma
UNION (ou UNION ALL)
de dois comandos SELECT (ou equivalentes)
(e não UNIONs aninhadas).
Se as duas cláusulas forem usadas, a coluna adicionada pela cláusula
SEARCH aparecerá antes das colunas adicionadas
pela cláusula CYCLE.
A consulta primária e as consultas WITH são todas
(conceitualmente) executadas ao mesmo tempo.
Isto implica que os efeitos de um comando de modificação de dados
na cláusula WITH não podem ser vistos de outras
partes da consulta, exceto pela leitura de sua saída
RETURNING.
Se dois desses comandos modificadores de dados tentarem modificar
a mesma linha, o resultado será indeterminado.
Uma propriedade chave das consultas WITH, é que
elas são normalmente avaliadas apenas uma vez por execução da
consulta primária, mesmo que a consulta primária se refira a elas
mais de uma vez.
Em particular, os comandos de modificação de dados são garantidos
de serem executados uma vez, e apenas uma vez, independentemente da
consulta primária ler toda ou parte de suas saídas.
Entretanto, a consulta WITH pode ser marcada
como NOT MATERIALIZED para remover esta garantia.
Neste caso, a consulta WITH pode ser mesclada na
consulta primária como se fosse um simples sub-SELECT
na cláusula FROM da consulta primária.
Isto irá resultar em computações duplicadas, se a consulta principal
se referir a esta consulta WITH mais de uma vez;
mas se cada uso exigir apenas algumas linhas da saída total da consulta
WITH, então NOT MATERIALIZED
pode produzir um ganho, permitindo que as consultas sejam
otimizadas em conjunto.
A cláusula NOT MATERIALIZED é ignorada se for
anexada a uma consulta WITH recursiva,
ou que não é livre de efeitos colaterais (ou seja, não é um
SELECT simples sem funções voláteis).
Por padrão, uma consulta WITH livre de efeitos
colaterais é incluída na consulta primária se for usada apenas
uma vez na cláusula FROM da consulta primária.
Isto permite a otimização conjunta dos dois níveis de consulta
em situações em que isto deveria ser semanticamente invisível.
Entretanto, esta inclusão pode ser evitada marcando a consulta
WITH como MATERIALIZED.
Isto pode ser útil, por exemplo, se a consulta WITH
estiver sendo usada como barreira de otimização para evitar que
o planejador escolha um plano ruim.
As versões do PostgreSQL anteriores à 12
nunca fizeram esta inclusão, portanto, as consultas escritas para
versões mais antigas podem depender de WITH para
atuar como barreira de otimização.
Veja Consultas WITH (Expressões de tabela comuns) para obter informações adicionais.
FROM
A cláusula FROM especifica uma ou mais tabelas
de origem para o comando SELECT.
Se forem especificadas várias origens, o resultado será o produto
cartesiano (junção cruzada) de todas as origens.
Mas são geralmente adicionadas condições de qualificação
(via cláusula WHERE), para restringir as linhas
retornadas a um pequeno subconjunto do produto cartesiano.
A cláusula FROM pode conter os seguintes elementos:
nome_da_tabela
O nome (opcionalmente qualificado pelo esquema) da tabela
ou visão existente.
Se for especificado ONLY antes do nome da
tabela, apenas esta tabela será incluída.
Se não for especificado ONLY, a tabela e
todas as suas tabelas descendentes (se houver) serão incluídas.
Opcionalmente, pode ser especificado * após
o nome da tabela para indicar explicitamente que as tabelas
descendentes serão incluídas.
alias
Nome substituto para o item da cláusula FROM
que contém o alias.
O alias é usado para abreviar, ou para eliminar ambiguidade
em autojunções (onde a mesma tabela é examinada várias vezes).
Quando é fornecido um alias, ele oculta inteiramente o
verdadeiro nome da tabela ou função;
por exemplo, dado FROM foo AS f, o restante
do comando SELECT deve referir-se a este item
da cláusula FROM como f,
e não como foo.
Se for escrito um alias, também poderá ser escrita uma lista
de alias de coluna para fornecer nomes substitutos para uma
ou mais colunas da tabela.
TABLESAMPLE método_de_amostragem ( argumento [, ...] ) [ REPEATABLE ( semente ) ]
A cláusula TABLESAMPLE colocada após o
nome_da_tabela,
indica que deve ser usado o
método_de_amostragem
especificado para recuperar um subconjunto das linhas dessa tabela.
Esta amostragem precede a aplicação de qualquer outro filtro,
como cláusulas WHERE.
A distribuição padrão do PostgreSQL
inclui dois métodos de amostragem, BERNOULLI
e SYSTEM, podendo ser instalados outros
métodos de amostragem no banco de dados por meio de extensões.
Os métodos de amostragem BERNOULLI e
SYSTEM aceitam um único
argumento,
que é a fração da tabela a ser amostrada, expressa como um
percentual entre 0 e 100.
Este argumento pode ser qualquer expressão com valor
do tipo de dados real.
(Outros métodos de amostragem podem aceitar mais argumentos,
ou argumentos diferentes.)
Cada um desses dois métodos retorna uma amostra escolhida
aleatoriamente da tabela contendo aproximadamente a porcentagem
das linhas da tabela especificada.
O método BERNOULLI varre toda a tabela,
selecionando ou ignorando linhas individuais de forma
independente com a probabilidade especificada.
O método SYSTEM faz amostragem no
nível de bloco, com cada bloco tendo a chance especificada
de ser selecionado;
são retornadas todas as linhas de cada bloco selecionado.
O método SYSTEM é muito mais
rápido que o método BERNOULLI quando são
especificadas pequenas porcentagens de amostragem, mas pode
retornar uma amostra menos aleatória da tabela como resultado
de efeitos de agrupamento.
A cláusula opcional REPEATABLE especifica um
número ou expressão
semente, a ser
usado para gerar números aleatórios dentro do método de amostragem.
O valor da semente pode ser qualquer valor de ponto flutuante
não nulo.
Duas consultas que especificam os mesmos valores de semente e
argumento
selecionarão a mesma amostra da tabela, se a tabela não tiver
sido alterada entre estas duas consultas.
Mas valores de semente diferentes geralmente produzem amostras
diferentes.
Se não for fornecido REPEATABLE, será
selecionada uma nova amostra aleatória para cada consulta,
com base em uma semente gerada pelo sistema.
Note que alguns métodos de amostragem adicionais não aceitam
REPEATABLE, produzindo sempre uma nova amostra
a cada uso. (Veja tsm_system_time e
tsm_system_rows, N.T.)
seleção
Pode aparecer um sub-SELECT na cláusula
FROM,
agindo como se sua saída tivesse sido criada como uma tabela
temporária durante este único comando SELECT.
Note que o sub-SELECT deve estar entre
parênteses, e pode ser fornecido um alias da mesma forma que
para uma tabela.
Também pode ser usado o comando VALUES aqui.
nome_da_consulta_WITH
A consulta WITH é referenciada escrevendo
seu nome, como se o nome da consulta fosse o nome da tabela.
(Na verdade, a consulta WITH oculta qualquer
tabela real com o mesmo nome para os propósitos da consulta
primária. Se necessário, pode ser feita referência a uma tabela
real com o mesmo nome qualificando o nome da tabela com o esquema.)
Pode ser fornecido um alias da mesma forma que para uma tabela.
nome_da_função
Podem aparecer chamadas de função na cláusula FROM.
(Isto é especialmente útil para funções que retornam conjuntos
de resultados, mas pode ser usada qualquer função.)
Isto age como se a saída da função tivesse sido criada como uma
tabela temporária durante este único comando SELECT.
Se o tipo de dados do resultado da função for composto
(incluindo o caso de uma função com vários parâmetros
OUT), cada atributo torna-se uma coluna
separada na tabela implícita.
Quando é adicionada a cláusula opcional
WITH ORDINALITY à chamada da função,
será anexada uma coluna adicional do tipo bigint
à(s) coluna(s) de resultado da função.
Esta coluna numera as linhas do conjunto de resultados da função,
começando em 1.
Por padrão, esta coluna se chama ordinality.
Pode ser fornecido um alias da mesma forma que para uma tabela.
Se for escrito um alias, também poderá ser escrita uma lista de
alias de coluna para fornecer nomes substitutos para um ou mais
atributos do tipo de dados de retorno composto da função,
incluindo a coluna ordinality, se presente.
Podem ser combinadas várias chamadas de função em um único item
da cláusula FROM, envolvendo-as com
ROWS FROM( ... ).
A saída desse item é a concatenação da primeira linha de cada
função, depois a segunda linha de cada função, etc.
Se algumas das funções produzirem menos linhas do que outras,
serão substituídos valores nulos pelos dados ausentes, de modo
que o número total de linhas retornadas seja sempre o mesmo da
função que produzir mais linhas.
Se a função for definida como retornando o tipo de dados
record, então deverá estar presente um alias
ou a palavra-chave AS, seguida por uma lista
de definição de colunas no formato
( .
A lista de definição de colunas deve corresponder ao número
e aos tipos de dados das colunas retornados pela função.
nome_da_coluna
tipo_de_dados [, ...
])
Quando se usa a sintaxe ROWS FROM( ... ),
se uma das funções exigir uma lista de definição de colunas,
é preferível colocar a lista de definição de colunas após a
chamada da função dentro de ROWS FROM( ... ).
Uma lista de definição de colunas somente pode ser colocada após
a construção ROWS FROM( ... ) se houver apenas
uma única função, e nenhuma cláusula
WITH ORDINALITY.
Para usar ORDINALITY junto com uma lista de
definição de colunas, deve ser usada a sintaxe
ROWS FROM( ... ), e colocada a lista de
definição de colunas dentro de ROWS FROM( ... ).
tipo_de_junçãoUm entre:
[ INNER ] JOIN
LEFT [ OUTER ] JOIN
RIGHT [ OUTER ] JOIN
FULL [ OUTER ] JOIN
Para os tipos de junção INNER e
OUTER é necessário especificar uma condição
de junção, ou seja, exatamente uma entre
ON ,
condição_de_junçãoUSING (,
ou coluna_de_junção [, ...])NATURAL. Veja o significado abaixo.
Uma cláusula JOIN junta dois itens da
cláusula FROM, que por conveniência serão
referidos como “tabelas”, embora na realidade possam
ser qualquer tipo de item da cláusula FROM.
Se for necessário, devem ser usados parênteses para determinar
a ordem de aninhamento.
Na ausência de parênteses, as junções se aninham da esquerda
para a direita.
Em qualquer caso, a cláusula JOIN liga mais
firmemente do que as vírgulas que separam os itens da lista
da cláusula FROM.
Todas as opções de JOIN são apenas uma
conveniência notacional, uma vez que não fazem nada que não se
possa fazer com um simples FROM e
WHERE.
LEFT OUTER JOIN retorna todas as linhas do
produto cartesiano qualificado (ou seja, todas as linhas
juntadas que passam pela condição de junção),
mais uma cópia de cada linha na tabela da esquerda para a qual
não há nenhuma linha da direita que passe pela condição de junção.
Esta linha à esquerda é estendida para toda a largura da tabela
juntada, inserindo valores nulos para as colunas à direita.
Note que apenas a própria condição da cláusula
JOIN é considerada ao decidir quais linhas
têm correspondências.
As condições externas são aplicadas posteriormente.
Inversamente, RIGHT OUTER JOIN retorna todas
as linhas juntadas, mais uma linha para cada linha à direita sem
correspondência (estendida com nulos à esquerda).
Esta é apenas uma notação conveniente, já que pode ser convertida
em LEFT OUTER JOIN trocando de lado as
tabelas esquerda e direita.
FULL OUTER JOIN retorna todas as linhas
juntadas, mais uma linha para cada linha à esquerda sem
correspondência (estendida com nulos à direita),
mais uma linha para cada linha à direita sem
correspondência (estendida com nulos à esquerda).
ON condição_de_junção
A condição_de_junção
é uma expressão que resulta em um valor do tipo de dados
boolean (semelhante à cláusula WHERE),
que especifica quais linhas em uma junção são consideradas
correspondentes.
USING ( coluna_de_junção [, ...] ) [ AS junção_usando_alias ]
Uma cláusula com a forma USING ( a, b, ... )
é uma forma abreviada de
ON tabela_esquerda.a = tabela_direita.a
AND tabela_esquerda.b = tabela_direita.b ....
Além disso, a cláusula USING implica que apenas
uma de cada par de colunas equivalentes será incluída na saída
da junção, e não as duas.
Se for especificado
junção_usando_alias,
este fornecerá um alias de tabela para as colunas da junção.
Apenas as colunas da junção listadas na cláusula
USING são endereçáveis por este nome.
Ao contrário de um alias
regular, este alias não oculta os nomes das tabelas juntadas
do restante da consulta.
Também, diferentemente de um
alias regular,
não se pode escrever uma lista de alias de coluna —
os nomes de saída das colunas da junção são os mesmos que
aparecem na lista da cláusula USING.
NATURAL
NATURAL é uma forma abreviada de uma lista
da cláusula USING mencionando todas as
colunas nas duas tabelas que possuem nomes correspondentes.
Se não houver nomes de colunas comuns, a condição
NATURAL é equivalente à condição
ON TRUE.
CROSS JOIN
CROSS JOIN equivale a
INNER JOIN ON (TRUE), ou seja,
nenhuma linha é removida por qualificação.
Elas produzem um produto cartesiano simples, o mesmo resultado
que se obteria ao listar as duas tabelas no nível superior de
FROM, mas restrito pela condição de junção
(se houver).
LATERAL
A palavra-chave LATERAL pode preceder um
item sub-SELECT da cláusula
FROM.
Isto permite ao sub-SELECT fazer referência
a colunas de itens da cláusula FROM que
aparecem antes na lista da cláusula FROM.
(Sem LATERAL, cada sub-SELECT
é avaliado independentemente, e por isto não pode fazer referência
cruzada a nenhum outro item da cláusula FROM.)
LATERAL também pode preceder um item
de chamada de função da cláusula FROM,
mas neste caso é apenas uma palavra ruído, porque a expressão
da função pode fazer referência a itens anteriores da cláusula
FROM de qualquer forma.
Um item LATERAL pode aparecer no nível
superior na lista da cláusula FROM,
ou numa árvore da cláusula JOIN.
No último caso, também pode fazer referência a qualquer item que
esteja no lado esquerdo de uma cláusula JOIN
que esteja no lado direito.
Quando um item da cláusula FROM contém
referências cruzadas LATERAL, a avaliação
procede da seguinte forma: para cada linha do item da cláusula
FROM fornecendo a(s) coluna(s) com referência
cruzada, ou conjunto de linhas de múltiplos itens da cláusula
FROM fornecendo as colunas, o item
LATERAL é avaliado usando os valores dessa
linha, ou conjunto de linhas das colunas.
A(s) linha(s) resultante(s) são juntadas como de costume
com as linhas das quais foram calculadas.
Isto se repete para cada linha, ou conjunto de linhas,
da(s) tabela(s) de origem da coluna.
As tabelas de origem da coluna devem ser INNER
ou LEFT juntadas ao item
LATERAL, caso contrário não haveria um conjunto
bem definido de linhas a partir das quais calcular cada conjunto
de linhas para o item LATERAL.
Assim, embora uma construção como
seja sintaticamente válida, na verdade não é permitido que
X RIGHT JOIN LATERAL YY faça referência a
X.
WHERE
A cláusula opcional WHERE tem a forma geral
WHERE condição
onde condição
é qualquer expressão que produz um resultado do tipo de dados
boolean.
Qualquer linha que não satisfaça esta condição será eliminada da
saída.
Uma linha satisfaz a condição se retornar verdade quando os valores
da linha forem substituídos por qualquer referência de variável.
Cláusula GROUP BY
A cláusula opcional GROUP BY tem a forma geral
GROUP BY [ ALL | DISTINCT ] elemento_de_agrupamento [, ...]
A cláusula GROUP BY condensa em uma única linha
todas as linhas selecionadas que compartilham os mesmos valores
para as expressões de agrupamento.
Uma expressão
usada em um
elemento_de_agrupamento
pode ser o nome de uma coluna de entrada, ou o nome ou número ordinal
de uma coluna de saída (item da lista SELECT),
ou uma expressão arbitrária formada a partir de valores de coluna
de entrada.
Em caso de ambiguidade, um nome em GROUP BY
será interpretado como um nome de coluna de entrada, em vez de um
nome de coluna de saída.
Se estiver presente uma das cláusulas GROUPING SETS,
ROLLUP ou CUBE como elementos
de agrupamento, então a cláusula GROUP BY como
um todo define um certo número de
conjuntos de agrupamentos independentes.
O efeito disso é equivalente a construir um UNION ALL
entre as subconsultas com os conjuntos de agrupamento individuais
como suas cláusulas GROUP BY.
A cláusula opcional DISTINCT remove conjuntos
duplicados antes do processamento; não
transforma o UNION ALL em um
UNION DISTINCT.
Para mais detalhes sobre o tratamento de conjuntos de agrupamento,
veja a GROUPING SETS, CUBE e ROLLUP.
As funções de agregação, se forem usadas, serão calculadas em todas
as linhas que compõem cada grupo, produzindo um valor separado para
cada grupo.
(Se houver funções de agregação, mas nenhuma cláusula
GROUP BY, a consulta será tratada como tendo
um único grupo compreendendo todas as linhas selecionadas.)
O conjunto de linhas alimentadas para cada função de agregação pode
ser filtrado adicionalmente anexando uma cláusula
FILTER à chamada da função de agregação; veja a
Expressões de agregação para obter mais informações.
Quando está presente uma cláusula FILTER,
apenas as linhas que correspondem a ela são incluídas na entrada
dessa função de agregação.
Quando está presente a cláusula GROUP BY,
ou qualquer função de agregação, não é válido para as expressões
na lista do SELECT fazerem referência a colunas
não agrupadas, exceto em funções de agregação, ou quando a coluna
não agrupada depende funcionalmente das colunas agrupadas,
caso contrário, haveria mais de um valor possível para retornar
para uma coluna não agrupada.
Uma dependência funcional existe se as colunas agrupadas
(ou um subconjunto delas) forem a chave primária da tabela
que contém a coluna não agrupada.
Lembre-se de que todas as funções de agregação são avaliadas antes
de avaliar qualquer expressão “escalar” na cláusula
HAVING ou na lista SELECT.
Isto significa que, por exemplo, uma expressão CASE
não pode ser usada para ignorar a avaliação de uma função de agregação;
veja a Regras para avaliação de expressão para obter mais informações.
No momento, não pode ser especificado
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE e FOR KEY SHARE com
GROUP BY.
HAVING
A cláusula opcional HAVING tem a forma geral
HAVING condição
onde condição é a
mesma especificada para a cláusula WHERE.
A cláusula HAVING elimina linhas de grupo
que não atendem à condição.
HAVING é diferente de WHERE:
WHERE filtra linhas individuais antes da aplicação
de GROUP BY, enquanto HAVING
filtra linhas agrupadas criadas por GROUP BY.
Cada coluna referenciada na
condição
deve referenciar sem ambiguidade uma coluna de agrupamento,
a menos que a referência apareça em uma função de agregação,
ou a coluna não agrupada seja funcionalmente dependente das colunas
de agrupamento.
A presença de HAVING transforma a consulta
em uma consulta agrupada, mesmo não havendo a cláusula
GROUP BY.
Isto é o mesmo que acontece quando a consulta contém funções de
agregação, mas nenhuma cláusula GROUP BY.
Todas as linhas selecionadas são consideradas para formar um único
grupo, e a lista SELECT e a cláusula
HAVING só podem fazer referência a colunas de
tabela de funções de agregação.
Esta consulta emite uma única linha se a condição
HAVING for verdadeira, e zero linhas se não
for verdadeira.
No momento, não pode ser especificado
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE e FOR KEY SHARE
com a cláusula HAVING.
WINDOW
A cláusula opcional WINDOW tem a forma geral
WINDOWnome_da_janelaAS (definição_da_janela) [, ...]
onde nome_da_janela é
um nome que pode ser referenciado em cláusulas OVER
ou definições de janela subsequentes, e
definição_da_janela é
[nome_de_janela_existente] [ PARTITION BYexpressão[, ...] ] [ ORDER BYexpressão[ ASC | DESC | USINGoperador] [ NULLS { FIRST | LAST } ] [, ...] ] [cláusula_de_quadro]
Se for especificado um
nome_de_janela_existente,
ele deverá se referir a uma entrada anterior na lista da cláusula
WINDOW; a nova janela copia sua cláusula de
particionamento dessa entrada, bem como sua cláusula de ordenação,
se houver.
Neste caso, a nova janela não pode especificar sua própria cláusula
PARTITION BY, e pode especificar
ORDER BY somente se a janela copiada não tiver uma.
A nova janela sempre usa sua própria cláusula de quadro; a
janela copiada não deve especificar uma cláusula de quadro.
Os elementos da lista PARTITION BY
são interpretados da mesma forma que os elementos de uma cláusula
GROUP BY,
exceto por serem sempre expressões simples, e nunca o nome ou número
de uma coluna de saída.
Outra diferença é que estas expressões podem conter chamadas de
funções de agregação, que não são permitidas em uma cláusula
GROUP BY regular.
Elas são permitidos aqui, porque o janelamento ocorre após o
agrupamento e a agregação.
De forma semelhante, os elementos da lista da cláusula
ORDER BY são interpretados da mesma forma
que os elementos no nível de comando da cláusula
ORDER BY,
exceto que as expressões são sempre tomadas como expressões simples,
e nunca o nome ou o número de uma coluna de saída.
A cláusula_de_quadro
opcional define o quadro da janela para
funções de janela que dependem do quadro (nem todas dependem).
O quadro da janela é um conjunto de linhas relacionadas para cada
linha da consulta (chamada linha corrente).
A cláusula_de_quadro
pode ser uma entre
{ RANGE | ROWS | GROUPS } início_de_quadro [ exclusão_de_quadro ]
{ RANGE | ROWS | GROUPS } BETWEEN início_de_quadro AND fim_de_quadro [ exclusão_de_quadro ]
onde início_de_quadro
e fim_de_quadro pode ser um entre
UNBOUNDED PRECEDINGdeslocamentoPRECEDING CURRENT ROWdeslocamentoFOLLOWING UNBOUNDED FOLLOWING
e exclusão_de_quadro pode ser um entre
EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS
Se fim_de_quadro for omitido, o padrão é
CURRENT ROW.
As restrições são que
início_de_quadro não pode ser
UNBOUNDED FOLLOWING,
fim_de_quadro não pode ser
UNBOUNDED PRECEDING,
e a escolha de fim_de_quadro
não pode aparecer antes na lista acima das opções de
início_de_quadro e
fim_de_quadro
que a escolha de início_de_quadro —
por exemplo,
RANGE BETWEEN CURRENT ROW AND
não é permitido.
deslocamento PRECEDING
A opção de enquadramento padrão é
RANGE UNBOUNDED PRECEDING,
que é o mesmo que
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW;
isto define o quadro como sendo todas as linhas desde o início da
partição até o último par da linha corrente
(uma linha que a cláusula ORDER BY da janela
considera equivalente à linha corrente; todas as linhas serão pares se
não houver ORDER BY).
Em geral, UNBOUNDED PRECEDING significa que o
quadro começa com a primeira linha da partição, e analogamente
UNBOUNDED FOLLOWING significa que o quadro
termina com a última linha da partição, independentemente do modo
RANGE, ROWS ou
GROUPS.
No modo ROWS, CURRENT ROW
significa que o quadro começa ou termina com a linha corrente;
mas no modo RANGE ou GROUPS,
significa que o quadro começa ou termina com o primeiro ou último
par da linha corrente na ordem estabelecida por
ORDER BY.
As opções
deslocamento PRECEDING e
deslocamento FOLLOWING
variam de significado dependendo do modo de quadro.
No modo ROWS, o
deslocamento é um número inteiro que
indica que o quadro começa, ou termina, tantas linhas antes ou
depois da linha corrente;
No modo GROUPS, o
deslocamento
é um número inteiro indicando que o quadro começa, ou termina, com
tantos grupos de pares antes ou depois do grupo de pares da linha
corrente, onde um grupo de pares é um grupo de
linhas que são equivalentes segundo a cláusula
ORDER BY da janela;
No modo RANGE, o uso da opção
deslocamento requer que haja exatamente
uma coluna ORDER BY na definição da janela.
Então, o quadro contém as linhas cujo valor da coluna de ordenação
não é inferior ao deslocamento
(para PRECEDING) ou superior
(para FOLLOWING)
ao valor da coluna de ordenação da linha corrente.
Nesses casos, o tipo de dados da expressão
deslocamento depende do tipo de dados
da coluna de ordenação.
Para colunas de ordenação numérica, é normalmente do mesmo tipo
de dados que a coluna de ordenação, mas para colunas de ordenação
por data e hora é do tipo de dados interval.
Em todos estes casos, o valor do
deslocamento deve ser não nulo e
não negativo.
Além disso, embora o deslocamento
não precise ser uma constante simples, não pode conter
variáveis, funções de agregação, ou funções de janela.
A opção exclusão_de_quadro permite que
as linhas ao redor da linha corrente sejam excluídas do quadro,
mesmo que pudessem ser incluídas segundo as opções de início e
fim do quadro.
A opção EXCLUDE CURRENT ROW
exclui a linha corrente do quadro.
A opção EXCLUDE GROUP exclui a linha corrente
e seus pares de ordenação do quadro.
A opção EXCLUDE TIES exclui quaisquer pares
da linha corrente do quadro, mas não a própria linha corrente.
A opção EXCLUDE NO OTHERS simplesmente
especifica explicitamente o comportamento padrão de não
excluir a linha corrente ou seus pares.
Tenha cuidado, porque o modo ROWS poderá
produzir resultados imprevisíveis se a ordem estabelecida por
ORDER BY não ordenar as linhas de modo único.
Os modos RANGE e GROUPS
são projetados para garantir que as linhas que são pares na ordem
estabelecida por ORDER BY sejam tratadas da mesma
forma: todas as linhas de um determinado grupo de pares estarão no
quadro, ou serão excluídas dele.
A finalidade de uma cláusula WINDOW é especificar
o comportamento das funções de janela que
aparecem na lista da consulta
SELECT,
ou na cláusula
ORDER BY.
Estas funções podem fazer referência às entradas da cláusula
WINDOW pelo nome em suas cláusulas
OVER.
Entretanto, uma entrada da cláusula WINDOW
não precisa ser referenciada em nenhum lugar; se não for usada
na consulta, é simplesmente ignorada.
É possível usar funções de janela sem nenhuma cláusula
WINDOW, já que uma chamada de função de janela
pode especificar sua definição de janela diretamente em sua
cláusula OVER.
No entanto, a cláusula WINDOW economiza digitação
quando a mesma definição de janela é necessária para mais de uma
função de janela.
No momento, não pode ser especificado
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE e FOR KEY SHARE
com a cláusula WINDOW.
As funções de janela são descritas em detalhes em Funções de janela, Chamadas de função de janela e Processamento de função de janela.
SELECT
A lista do SELECT (entre as palavras-chave
SELECT e FROM)
especifica expressões que formam as linhas de saída do comando
SELECT.
As expressões podem (e normalmente o fazem) se referir a colunas
computadas na cláusula FROM.
Assim como em uma tabela, cada coluna de saída de um comando
SELECT tem um nome.
Em um comando SELECT simples, este nome é usado
apenas para rotular a coluna para exibição, mas quando o
SELECT é uma subconsulta de uma consulta maior,
o nome é visto pela consulta maior como o nome da coluna da tabela
virtual produzida pela subconsulta.
Para especificar o nome a ser usado para uma coluna de saída, deve
ser escrito AS
nome_de_saída
após a expressão da coluna.
(Pode ser omitido o AS, mas apenas se o nome de
saída desejado não corresponder a nenhuma palavra-chave do
PostgreSQL
(veja Apêndice C).
Para proteção contra possíveis adições futuras de palavras-chave,
é recomendável que sempre se escreva o AS,
ou que se coloque o nome de saída entre aspas.)
Se não for especificado o nome da coluna, será escolhido um nome
automaticamente pelo PostgreSQL.
Se a expressão da coluna for uma simples referência de coluna,
o nome escolhido será o mesmo que o nome dessa coluna.
Em casos mais complexos, pode ser usado um nome de função ou de
tipo de dados, ou o sistema pode recorrer a um nome gerado, como
?column?.
O nome da coluna de saída pode ser usado para se referir ao valor
da coluna nas cláusulas ORDER BY e
GROUP BY, mas não nas cláusulas
WHERE ou HAVING;
nessas cláusulas deve ser escrita a expressão em seu lugar.
Em vez de uma expressão, pode ser escrito *
na lista de saída como um atalho para todas as colunas das linhas
selecionadas.
Além disso, também pode ser escrito
como um atalho para as colunas provenientes apenas dessa tabela.
Nesses casos não é possível especificar novos nomes usando o
nome_da_tabela.*AS; os nomes das colunas de saída serão iguais
aos nomes das colunas da tabela.
Segundo o padrão SQL, as expressões na
lista de saída devem ser calculadas antes de aplicar
DISTINCT, ORDER BY, ou
LIMIT.
Isto é obviamente necessário ao usar DISTINCT,
caso contrário não fica claro quais valores estão sendo diferenciados.
No entanto, em muitos casos, é conveniente que as expressões de saída
sejam calculadas após ORDER BY e
LIMIT; particularmente se a lista de saída
contiver quaisquer funções voláteis ou dispendiosas.
Com este comportamento, a ordem das avaliações das funções fica mais
intuitiva, e não haverá avaliações correspondentes a linhas que
nunca aparecem na saída.
O PostgreSQL avaliará efetivamente as
expressões de saída após a classificação e aplicação de limites,
desde que estas expressões não sejam referenciadas em
DISTINCT, ORDER BY ou
GROUP BY.
(Como contra-exemplo, SELECT f(x) FROM tab ORDER BY 1
claramente deve avaliar f(x) antes de classificar.)
As expressões de saída que contêm funções que retornam conjunto são
efetivamente avaliadas após a classificação e antes da aplicação dos
limites, de modo que LIMIT atuará para cortar
a saída de uma função que retorna conjunto.
As versões do PostgreSQL anteriores a 9.6 não ofereciam nenhuma garantia sobre o momento de avaliação das expressões de saída versus classificação e aplicação de limites; era dependente da forma do plano de consulta escolhido.
DISTINCT
Se for especificado SELECT DISTINCT, todas as
linhas duplicadas serão removidas do conjunto de resultados
(é mantida uma linha de cada grupo de duplicadas).
SELECT ALL especifica o oposto: todas as linhas
são mantidas; este é o padrão.
SELECT DISTINCT ON (
mantém apenas a primeira linha de cada conjunto de linhas onde
as expressões fornecidas são avaliadas como iguais.
As expressões expressão [, ...] )DISTINCT ON são interpretadas usando
as mesmas regras usadas para ORDER BY (veja acima).
Note que a “primeira linha” de cada conjunto é
imprevisível, a menos que seja usado ORDER BY
para garantir que a linha desejada apareça primeiro.
Por exemplo:
SELECT DISTINCT ON (local) local, hora, relatório
FROM boletim_meteorológico
ORDER BY local, hora DESC;
recupera o boletim meteorológico mais recente para cada local.
Mas se não tivesse sido usado ORDER BY para
forçar a ordem decrescente dos valores da hora para cada local, teria
sido obtido um relatório com uma hora imprevisível para cada local.
As expressões DISTINCT ON devem corresponder
às expressões ORDER BY mais à esquerda.
A cláusula ORDER BY normalmente contém expressões
adicionais que determinam a precedência desejada das linhas dentro
de cada grupo DISTINCT ON.
No momento, não pode ser especificado
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE e FOR KEY SHARE com
DISTINCT.
UNION
A cláusula UNION tem a forma geral
comando_selectUNION [ ALL | DISTINCT ]comando_select
onde comando_select é
qualquer comando SELECT sem uma cláusula
ORDER BY, LIMIT,
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE, ou FOR KEY SHARE.
(ORDER BY e LIMIT podem ser
anexados a uma subexpressão se estiverem entre parênteses.
Sem parênteses, estas cláusulas serão aplicadas ao resultado da
cláusula UNION, e não à sua expressão de entrada
à direita.)
O operador UNION computa a união dos
conjuntos de linhas retornados pelos comandos
SELECT envolvidos.
Uma linha está na união de dois conjuntos de resultados se aparecer
em pelo menos um dos conjuntos de resultados.
Os dois comandos SELECT que representam os
operandos diretos da cláusula UNION devem
produzir o mesmo número de colunas, e as colunas correspondentes
devem ser de tipos de dados compatíveis.
O resultado da cláusula UNION não contém nenhuma
linha duplicada, a menos que seja especificada a opção
ALL, que impede a eliminação de linhas duplicadas.
(Portanto, UNION ALL é geralmente
muito mais rápida do que UNION,
devendo ser usada quando for possível.)
Pode ser escrito DISTINCT para especificar
explicitamente o comportamento padrão de eliminação das linhas
duplicadas.
Múltiplas cláusulas UNION no mesmo comando
SELECT são avaliadas da esquerda para a direita,
a menos que seja indicado de outra forma usando parênteses.
No momento, não pode ser especificado
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE e FOR KEY SHARE,
seja para o resultado ou para qualquer entrada da cláusula
UNION.
INTERSECT
A cláusula INTERSECT tem a forma geral
comando_selectINTERSECT [ ALL | DISTINCT ]comando_select
onde comando_select
é qualquer comando SELECT sem uma cláusula
ORDER BY, LIMIT,
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE, ou FOR KEY SHARE.
O operador INTERSECT computa a interseção dos
conjuntos de linhas retornados pelos comandos
SELECT envolvidos.
Uma linha está na interseção dos dois conjuntos de resultados
se aparecer nos dois conjuntos de resultados.
O resultado da cláusula INTERSECT não contém
nenhuma linha duplicada, a menos que seja especificada a opção
ALL.
Com a opção ALL, uma linha que tem
m duplicações na tabela à esquerda,
e n duplicações na tabela à direita,
aparecerá min(m, n)
vezes no conjunto de resultados.
Pode ser escrito DISTINCT para especificar
explicitamente o comportamento padrão de eliminação das linhas
duplicadas.
Múltiplas cláusulas INTERSECT no mesmo comando
SELECT são avaliadas da esquerda para a direita,
a menos que seja indicado de outra forma usando parênteses.
A cláusula INTERSECT liga mais firmemente do que
a cláusula UNION.
Ou seja, A UNION B INTERSECT C será interpretada
como A UNION (B INTERSECT C).
No momento, não pode ser especificado
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE e FOR KEY SHARE,
seja para o resultado
ou para qualquer entrada da cláusula INTERSECT.
EXCEPT
A cláusula EXCEPT tem a forma geral
comando_selectEXCEPT [ ALL | DISTINCT ]comando_select
onde comando_select
é qualquer comando SELECT sem uma cláusula
ORDER BY, LIMIT,
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE, ou FOR KEY SHARE.
O operador EXCEPT computa o conjunto de linhas
que estão no resultado do comando SELECT da
esquerda, mas não estão no resultado do comando da direita.
O resultado de EXCEPT não contém nenhuma linha
duplicada, a menos que a opção ALL seja especificada.
Com a opção ALL, uma linha que tem
m duplicações na tabela à esquerda, e
n duplicações na tabela à direita, aparecerá
max(m-n, 0)
vezes no conjunto de resultados.
Pode ser escrito DISTINCT para especificar
explicitamente o comportamento padrão de eliminação das linhas
duplicadas.
Múltiplas cláusulas EXCEPT no mesmo comando
SELECT são avaliadas da esquerda para a direita,
a menos que seja indicado de outra forma usando parênteses.
A cláusula EXCEPT liga no mesmo nível que
a cláusula UNION.
No momento, não pode ser especificado
FOR NO KEY UPDATE, FOR UPDATE,
FOR SHARE e FOR KEY SHARE,
seja para o resultado
ou para qualquer entrada da cláusula EXCEPT.
ORDER BY
A cláusula opcional ORDER BY tem a forma geral
ORDER BYexpressão[ ASC | DESC | USINGoperador] [ NULLS { FIRST | LAST } ] [, ...]
A cláusula ORDER BY faz com que as linhas do
resultado sejam classificadas conforme a(s) expressão(ões)
especificada(s).
Se duas linhas forem iguais segundo a expressão mais
à esquerda, elas serão comparadas segundo a expressão seguinte,
e assim por diante.
Se forem iguais de acordo com todas as expressões especificadas,
serão retornadas em uma ordem dependente da implementação.
Cada expressão
pode ser o nome ou número ordinal de uma coluna de saída
(item da lista SELECT), ou pode ser uma expressão
arbitrária formada a partir de valores de coluna de entrada.
O número ordinal refere-se à posição ordinal (da esquerda para
a direita) da coluna de saída.
Este recurso permite definir uma ordenação com base em uma coluna
que não possui um nome único.
Isto nunca é inteiramente necessário, porque sempre é possível
atribuir um nome a uma coluna de saída usando a cláusula
AS.
Também é possível usar expressões arbitrárias na cláusula
ORDER BY, incluindo colunas que não aparecem
na lista de saída do comando SELECT.
Assim, o seguinte comando é válido:
SELECT name FROM distributors ORDER BY code;
Uma limitação desse recurso é que uma cláusula
ORDER BY aplicada ao resultado de uma cláusula
UNION, INTERSECT, ou
EXCEPT, só pode especificar um nome ou número
de coluna de saída, e não uma expressão.
Se a expressão da cláusula ORDER BY for um nome
simples, que corresponda a um nome de coluna de saída e a um nome
de coluna de entrada, a cláusula ORDER BY irá
interpretá-lo como o nome da coluna de saída.
Esta escolha é o oposto da que a cláusula GROUP BY
faz na mesma situação.
Esta inconsistência é feita para ficar compatível com o padrão
SQL.
Como opção, pode-se adicionar a palavra-chave ASC
(ascendente) ou DESC (descendente) após qualquer
expressão na cláusula ORDER BY.
Se não especificado, é assumido ASC por padrão.
Como alternativa, pode ser especificado um nome de operador de
ordenação específico na cláusula USING.
O operador de ordenação deve ser um membro
“menor que” ou “maior que”
de alguma família de operadores de Árvore-B.
ASC é geralmente equivalente a
USING <, e DESC
é geralmente equivalente a USING >.
(Mas o criador de um tipo de dados definido pelo usuário pode
definir exatamente qual é a ordem de classificação padrão,
e pode corresponder a operadores com outros nomes.)
Se for especificado NULLS LAST, os valores
nulos serão classificados após todos os valores não nulos;
se for especificado NULLS FIRST, os valores
nulos serão classificados antes de todos os valores não nulos.
Se não for especificado nenhum dos dois, o comportamento padrão será
NULLS LAST quando ASC
for especificado ou for implícito, e NULLS FIRST
quando DESC for especificado (portanto, o padrão
é agir como se os nulos fossem maiores que os não nulos).
Quando é especificado USING, a ordem padrão dos
nulos depende se o operador é “menor que”,
ou “maior que”.
Note que as opções de ordenação se aplicam apenas à expressão
que elas seguem; por exemplo, ORDER BY x, y DESC não
significa a mesma coisa que ORDER BY x DESC, y DESC.
Os dados de cadeia de caracteres são classificados segundo
a ordenação que se aplica à coluna que está sendo classificada.
Isto pode ser mudado se necessário, incluindo uma cláusula
COLLATE na
expressão, por exemplo,
ORDER BY minha_coluna COLLATE "pt_BR".
Para mais obter informações, veja
Expressões de ordenação e
Suporte a ordenação.
LIMIT
A cláusula LIMIT consiste em duas subcláusulas
independentes:
LIMIT { contador | ALL }
OFFSET início
O parâmetro contador
especifica o número máximo de linhas a serem retornadas, enquanto
início especifica o
número de linhas a serem ignoradas antes de começar a retornar linhas.
Quando os dois são especificados,
início
linhas são saltadas antes de começar a contar o
contador
linhas a serem retornadas.
Se a expressão contador
for avaliada como NULL, ela será tratada como
LIMIT ALL, ou seja, sem limite.
Se início
for avaliado como NULL, ele será tratada como
OFFSET 0.
O padrão SQL:2008 introduziu uma sintaxe diferente para obter o mesmo resultado, que o PostgreSQL também dá suporte. Ela é:
OFFSETinício{ ROW | ROWS } FETCH { FIRST | NEXT } [contador] { ROW | ROWS } { ONLY | WITH TIES }
Nesta sintaxe, o valor de
início ou do
contador é exigido pelo
padrão como uma constante literal, um parâmetro, ou um nome de variável;
como extensão do PostgreSQL,
são permitidas outras expressões, mas geralmente precisam ser
colocadas entre parênteses para evitar ambiguidade.
Se for omitido o contador
em uma cláusula FETCH, o padrão será 1.
A opção WITH TIES é usada para retornar quaisquer
linhas adicionais que se igualam na última posição no conjunto de
resultados segundo a cláusula ORDER BY;
neste caso ORDER BY é obrigatório, enquanto
SKIP LOCKED não é permitido.
ROW e ROWS, assim como
FIRST e NEXT, são palavras
ruído que não influenciam os efeitos dessas cláusulas.
Segundo o padrão, a cláusula OFFSET deve
vir antes da cláusula FETCH, se as duas estiverem
presentes; mas o PostgreSQL é mais
flexível e permite qualquer ordem.
Ao usar LIMIT, é uma boa ideia usar a cláusula
ORDER BY que restringe as linhas de resultado em
uma ordem única.
Caso contrário, será obtido um subconjunto imprevisível das linhas
da consulta — pode-se estar querendo da décima à vigésima linha,
mas da décima à vigésima linha em que ordem? Não se sabe em que ordem,
a menos que seja especificado ORDER BY.
O planejador de consulta leva LIMIT em consideração
ao gerar um plano para a consulta, então é muito provável que se
obtenha planos diferentes (resultando em diferentes ordens de linha)
dependendo do que é usado para LIMIT e
OFFSET.
Assim, utilizar valores diferentes de LIMIT e
OFFSET para selecionar subconjuntos diferentes
de um resultado da consulta
dará resultados inconsistentes,
a menos que se imponha uma ordem previsível de resultados com
ORDER BY.
Isto não é um bug;
isto é uma consequência inerente do fato de que o padrão
SQL não promete entregar os resultados de uma
consulta em qualquer ordem específica, a menos que seja usado
ORDER BY para impor a ordem.
É possível que até execuções repetidas da mesma consulta com a
cláusula LIMIT retornem diferentes subconjuntos
de linhas de uma tabela, se não houver ORDER BY
para impor a seleção de um subconjunto determinístico.
Novamente, isto não é um bug;
o determinismo dos resultados simplesmente não é garantido neste caso.
As cláusulas FOR UPDATE,
FOR NO KEY UPDATE, FOR SHARE e
FOR KEY SHARE
são cláusulas de bloqueio;
afetam como o comando SELECT bloqueia
as linhas conforme elas são obtidas da tabela.
A cláusula de bloqueio tem a forma geral
FORforça_de_bloqueio[ OFreferência_FROM[, ...] ] [ NOWAIT | SKIP LOCKED ]
onde a força_de_bloqueio pode ser uma entre
UPDATE NO KEY UPDATE SHARE KEY SHARE
referência_FROM deve
ser um alias de tabela
ou um nome_da_tabela
não oculto referenciado na cláusula FROM.
Para obter mais informações sobre cada modo de bloqueio no nível
de linha, veja Modos de bloqueio no nível de linha.
Para evitar que a operação aguarde por outras transações, deve ser usada
a opção NOWAIT ou SKIP LOCKED.
Com NOWAIT, se uma linha selecionada não puder ser
bloqueada imediatamente, a consulta relata um erro, em vez de aguardar.
Com SKIP LOCKED, são ignoradas quaisquer linhas
selecionadas que não puderem ser bloqueadas imediatamente.
Ignorar as linhas bloqueadas fornece uma visão inconsistente dos dados;
portanto, não é adequado para o trabalho de uso geral, mas pode ser
usado para evitar a contenção de bloqueio com vários consumidores
acessando uma tabela semelhante à fila.
Note que NOWAIT e
SKIP LOCKED se aplicam apenas ao(s) bloqueio(s)
no nível de linha — o bloqueio ROW SHARE
no nível de tabela ainda é realizado da maneira comum
(veja o Controle de concorrência).
Pode ser usado primeiro
LOCK com a opção
NOWAIT, se for necessário adquirir o bloqueio
no nível de tabela sem aguardar.
Se forem indicadas tabelas específicas em uma cláusula de bloqueio,
apenas as linhas provenientes dessas tabelas serão bloqueadas;
quaisquer outras tabelas presentes no comando SELECT
serão simplesmente lidas como de costume.
Uma cláusula de bloqueio sem uma lista de tabelas afeta todas as
tabelas usadas no comando.
Se uma cláusula de bloqueio for aplicada a uma visão ou subconsulta,
ela afetará todas as tabelas usadas na visão ou na subconsulta.
Entretanto, estas cláusulas não se aplicam a consultas
WITH referenciadas pela consulta primária.
Se for desejado que ocorra bloqueio de linha numa consulta
WITH, deve ser especificada uma cláusula de bloqueio
dentro da WITH.
Podem ser escritas várias cláusulas de bloqueio, se for necessário
especificar comportamentos de bloqueio diferentes para tabelas
específicas.
Se a mesma tabela for mencionada (ou implicitamente afetada)
por mais de uma cláusula de bloqueio, ela será processada como
se fosse atingida apenas pela cláusula mais forte.
De forma semelhante, uma tabela será processada como
NOWAIT se isto for especificado em alguma das
cláusulas que a afetam.
Caso contrário, será processada como SKIP LOCKED
se isto for especificado em alguma das cláusulas que a afetam.
As cláusulas de bloqueio não podem ser usadas em contextos onde as linhas retornadas não podem ser claramente identificadas com linhas individuais de tabela; por exemplo, não podem ser usadas com agregações.
Quando uma cláusula de bloqueio aparece no nível mais alto de um
comando SELECT, as linhas bloqueadas são
exatamente aquelas retornadas pela consulta; no caso de uma
consulta de junção, as linhas bloqueadas são aquelas que contribuem
para as linhas de junção retornadas.
Além disso, as linhas que atendiam às condições da consulta no
instantâneo da consulta serão bloqueadas, embora não sejam retornadas
se forem atualizadas após o instantâneo e não satisfizerem mais as
condições da consulta.
Se for usada uma cláusula LIMIT, o bloqueio
é encerrado logo após serem retornadas linhas suficientes para
satisfazer o limite (mas note-se que as linhas saltadas devido ao
OFFSET são bloqueadas).
De forma semelhante, se for usada uma cláusula de bloqueio na consulta
de um cursor, apenas as linhas realmente recuperadas ou percorridas
pelo cursor serão bloqueadas.
Quando uma cláusula de bloqueio aparece em um
sub-SELECT, as linhas bloqueadas são as
retornadas à consulta externa pela subconsulta.
Isto pode envolver menos linhas do que a inspeção da subconsulta
sugere, uma vez que as condições da consulta externa podem ser
usadas para otimizar a execução da subconsulta. Por exemplo,
SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5;
bloqueia apenas as linhas com col1 = 5, muito
embora esta condição não esteja textualmente dentro da subconsulta.
As versões anteriores falhavam em preservar um bloqueio atualizado por um ponto de salvamento posterior. Por exemplo, o código
BEGIN; SELECT * FROM mytable WHERE key = 1 FOR UPDATE; SAVEPOINT s; UPDATE mytable SET ... WHERE key = 1; ROLLBACK TO s;
deixaria de preservar o bloqueio FOR UPDATE
após o ROLLBACK TO.
Isto foi corrigido na versão 9.3.
É possível que um comando SELECT,
executando no nível de isolamento de transação
READ COMMITTED, usando
ORDER BY e uma cláusula de bloqueio, retorne
linhas fora de ordem.
Isto acontece, porque ORDER BY é aplicado primeiro.
O comando classifica o resultado, mas pode então ficar preso
tentando obter o bloqueio em uma ou mais das linhas.
Depois que o SELECT é desbloqueado,
alguns dos valores da coluna de ordenação podem ter sido modificados,
fazendo com que estas linhas pareçam estar fora de ordem
(embora estejam em ordem em termos dos valores originais da coluna).
Esta situação pode ser contornada se necessário, colocando a cláusula
FOR UPDATE/SHARE em uma subconsulta, por exemplo:
SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1;
Deve-se observar que esta forma do comando resulta no bloqueio de
todas as linhas de mytable, enquanto colocar
o FOR UPDATE no nível superior bloquearia apenas
as linhas realmente retornadas,
podendo causar uma diferença de desempenho significativa,
especialmente se ORDER BY for combinado com
LIMIT, ou outras restrições.
Portanto, esta técnica é recomendada apenas se forem esperadas
atualizações simultâneas das colunas de ordenação, e for necessário
um resultado classificado sem erros.
No nível de isolamento de transação REPEATABLE READ
ou SERIALIZABLE isto causaria uma falha de
serialização (com SQLSTATE igual a
'40001'), portanto, não há possibilidade de
receber linhas fora de ordem nesses níveis de isolamento.
TABLEO comando
TABLE nome_da_tabela
é equivalente a
SELECT * FROM nome_da_tabela
Pode ser usado como um comando de nível superior, ou como uma variante
de sintaxe que economiza espaço em partes de consultas complexas.
Somente WITH, UNION,
INTERSECT, EXCEPT,
ORDER BY, LIMIT,
OFFSET, FETCH,
e as cláusulas de bloqueio FOR
podem ser usadas com TABLE;
a cláusula WHERE, e qualquer forma de agregação,
não podem ser usadas com TABLE.
Para fazer a junção da tabela films com a tabela
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 somar a coluna len de todos os filmes,
agrupando os 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 somar a coluna len de todos os filmes,
agrupando os resultados por kind,
e mostrando somente os grupos com totais inferiores a 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
Os dois exemplos a seguir são formas idênticas de classificar os
resultados individuais de acordo com o conteúdo da segunda coluna
(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
O próximo exemplo mostra como obter a união das tabelas
distributors e actors,
restringindo os resultados para aqueles cujos nomes dos distribuidores
iniciam com a letra W em cada tabela.
Somente são desejadas linhas distintas, então é omitida
a palavra-chave 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 exemplo mostra como usar uma função na cláusula
FROM, com e sem uma lista de definição de colunas:
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
A seguir está o exemplo de uma função com uma coluna de ordinalidade adicionada:
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 linhas)
Este exemplo mostra como usar uma cláusula WITH
simples:
WITH t AS (
SELECT random() as x FROM generate_series(1, 3)
)
SELECT * FROM t
UNION ALL
SELECT * FROM t;
x
----------------------
0.7929177761979771
0.008855797525941123
0.15284504737436677
0.7929177761979771
0.008855797525941123
0.15284504737436677
(6 linhas)
Deve-se observar que a consulta WITH foi avaliada
apenas uma vez, de modo que foram obtidos dois conjuntos dos mesmos
três valores aleatórios.
Este exemplo usa WITH RECURSIVE para encontrar
todos os subordinados (diretos ou indiretos) da funcionária
Mary, e seu nível de indireção, a partir de uma
tabela que mostra apenas os subordinados diretos:
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;
Deve-se observar a forma típica das consultas recursivas:
uma condição inicial, seguida por UNION,
seguida pela parte recursiva da consulta.
Deve-se ter certeza de que a parte recursiva da consulta por fim não
retornará nenhuma tupla, ou então a consulta entrará num ciclo sem fim.
(Veja Consultas WITH (Expressões de tabela comuns) para obter mais exemplos.)
Este exemplo usa LATERAL para aplicar a função
que retorna conjunto get_product_names() para
cada linha da tabela manufacturers:
SELECT m.name AS mname, pname FROM manufacturers m, LATERAL get_product_names(m.id) pname;
Os fabricantes que não possuem nenhum produto no momento não aparecem no resultado, porque é uma junção interna. Se fosse desejado incluir os nomes desses fabricantes no resultado, poderia ser escrito:
SELECT m.name AS mname, pname FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true;
Exemplo 86. Exemplo do tradutor
Uso dos operadores UNION, INTERSECT e EXCEPT
Este exemplo mostra o uso dos operadores UNION,
INTERSECT e EXCEPT
sobre duas séries numéricas geradas pela função
generate_series contendo os valores
(1, 2, 3) e (1, 3, 5), respectivamente.
SELECT * FROM generate_series(1, 3) UNION SELECT * FROM generate_series(1, 5, 2);
generate_series
-----------------
1
3
5
2
(4 linhas)
SELECT * FROM generate_series(1, 3) INTERSECT SELECT * FROM generate_series(1, 5, 2);
generate_series
-----------------
1
3
(2 linhas)
SELECT * FROM generate_series(1, 3) EXCEPT SELECT * FROM generate_series(1, 5, 2);
generate_series
-----------------
2
(1 linha)
Note que no caso do operador UNION
são retornados todos os valores, mas sem repetição;
no caso do operador INTERSECT
são retornados os valores presentes nas duas sequências;
e no caso do operador EXCEPT
é retornado o valor presente na primeira sequência
que não está presente na segunda sequência.
Veja Funções geradoras de séries
para obter mais informações sobre a função
generate_series.
É claro que o comando SELECT é compatível com o
padrão SQL, mas existem algumas extensões e
alguns recursos ausentes.
FROM omitidas
O PostgreSQL permite omitir a cláusula
FROM, tendo uso direto para calcular os
resultados de expressões simples:
SELECT 2+2;
?column?
----------
4
Alguns outros bancos de dados SQL não permitem
fazer isto, exceto introduzindo de uma tabela fictícia de uma linha
a partir da qual fazer o SELECT.
SELECT vazias
A lista de expressões de saída após o SELECT pode
estar vazia, produzindo uma tabela de resultados zero-colunas.
Esta não é uma sintaxe válida segundo o padrão SQL.
O PostgreSQL permite isto para ser
consistente com a permissão de tabelas zero-colunas.
Entretanto, não é permitida uma lista vazia quando é usado
DISTINCT.
AS
No padrão SQL, a palavra-chave opcional
AS antes de um nome de coluna de saída pode ser
omitida sempre que o novo nome de coluna for um nome de coluna válido
(ou seja, não for idêntico a qualquer palavra-chave reservada).
PostgreSQL é um pouco mais restritivo:
AS é necessário se o nome da nova coluna
corresponder a qualquer palavra-chave, reservada ou não.
A prática recomendada é usar AS, ou nomes de
colunas de saída entre aspas, para evitar qualquer possível
conflito contra futuras adições de palavras-chave.
Nos itens da cláusula FROM, tanto o padrão
SQL quanto o PostgreSQL
permitem que seja omitido o AS antes de um alias
que seja uma palavra-chave não reservada.
Mas isto é impraticável para nomes de coluna de saída, devido a
ambiguidades sintáticas.
SELECT no FROM
Segundo o padrão SQL, um subcomando
SELECT na lista FROM
deve ter um alias.
No PostgreSQL este alias pode ser omitido.
ONLY e herança
O padrão SQL requer o uso de parênteses ao redor
do nome da tabela ao escrever ONLY, por exemplo,
SELECT * FROM ONLY (tab1), ONLY (tab2) WHERE ....
O PostgreSQL considera estes parênteses
opcionais.
O PostgreSQL permite ser escrito um
* à direita para especificar explicitamente o
comportamento não-ONLY de incluir as tabelas filhas.
O padrão SQL não permite isto.
(Estes pontos se aplicam igualmente a todos os comandos
SQL que dão suporte a opção
ONLY.)
TABLESAMPLE
A cláusula TABLESAMPLE é atualmente aceita apenas
em tabelas regulares e visões materializadas.
Segundo o padrão SQL, deve ser possível
aplicá-la a qualquer item da cláusula FROM.
FROM
O PostgreSQL permite ser escrita
uma chamada de função diretamente como um membro da lista
da cláusula FROM.
Pelo padrão SQL seria necessário agrupar a chamada
de função em um sub-SELECT; ou seja, a sintaxe
FROM
é aproximadamente equivalente a
func(...) aliasFROM LATERAL (SELECT .
Note que func(...)) aliasLATERAL é considerado implícito;
isto acontece porque o padrão SQL requer a semântica
LATERAL para um item UNNEST()
na cláusula FROM.
O PostgreSQL trata UNNEST()
da mesma forma que outras funções que retornam conjunto.
GROUP BY e ORDER BY
No padrão SQL-92, uma cláusula ORDER BY
só pode usar nomes ou números de colunas de saída,
enquanto uma cláusula GROUP BY pode usar apenas
expressões baseadas em nomes de colunas de entrada.
O PostgreSQL estende cada uma dessas
cláusulas para permitir a outra escolha também
(mas usa a interpretação do padrão se houver ambiguidade).
O PostgreSQL também permite que as duas
cláusulas especifiquem expressões arbitrárias.
Note que os nomes que aparecem em uma expressão sempre serão
considerados sendo nomes de colunas de entrada, e não nomes
de colunas de saída.
O padrão SQL:1999, e posteriores, usam uma definição ligeiramente
diferente que não é totalmente compatível com o SQL-92.
No entanto, geralmente o
PostgreSQL interpreta uma expressão
ORDER BY ou GROUP BY
da mesma forma que o SQL:1999.
O PostgreSQL reconhece dependência
funcional (permitindo que sejam omitidas colunas de
GROUP BY) somente quando a chave primária
de uma tabela está incluída na lista da cláusula
GROUP BY.
O padrão SQL especifica condições adicionais
que devem ser reconhecidas.
LIMIT e OFFSET
As cláusulas LIMIT e OFFSET
são sintaxes específicas do PostgreSQL,
também usadas pelo MySQL.
O padrão SQL:2008 introduziu as cláusulas
OFFSET ... FETCH {FIRST|NEXT} ... para a mesma
funcionalidade, conforme mostrado acima na Cláusula LIMIT.
Esta sintaxe também é usada pelo IBM DB2.
(Aplicações escritas para Oracle
frequentemente usam uma solução envolvendo a coluna
rownum gerada automaticamente, que não está
disponível no PostgreSQL,
para implementar os efeitos dessas cláusulas.)
FOR NO KEY UPDATE, FOR UPDATE, FOR SHARE, FOR KEY SHARE
Embora FOR UPDATE conste no padrão
SQL, o padrão permite apenas como opção de
DECLARE CURSOR.
O PostgreSQL o permite em qualquer
consulta SELECT, bem como em
sub-SELECTs, mas isto é uma extensão.
As variantes FOR NO KEY UPDATE,
FOR SHARE e FOR KEY SHARE,
assim como as opções NOWAIT e
SKIP LOCKED, não constam no padrão.
WITH
O PostgreSQL permite que
INSERT, UPDATE, e
DELETE sejam usados nas consultas
WITH.
Isto não consta no padrão SQL.
DISTINCT ON ( ... )
é uma extensão ao padrão SQL.
ROWS FROM( ... )
é uma extensão ao padrão SQL.
As opções MATERIALIZED e
NOT MATERIALIZED da cláusula WITH
são extensões do padrão SQL.