SELECT

SELECT, TABLE, WITH — recupera linhas de uma tabela ou visão

Sinopse

[ WITH [ RECURSIVE ] consulta_WITH [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expressão [, ...] ) ] ]
    [ { *
      | expressão [
          [ AS ] nome_de_saída ]
      }
      [, ...]
    ]
    [ FROM item_FROM
      [, ...]
    ]
    [ WHERE condição ]
    [ GROUP BY [ ALL | DISTINCT ] elemento_de_agrupamento
      [, ...]
    ]
    [ HAVING condição ]
    [ WINDOW nome_da_janela
        AS ( definição_da_janela )
        [, ...]
    ]
    [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] seleção ]
    [ ORDER BY expressão
        [ ASC | DESC | USING operador ]
        [ NULLS { FIRST | LAST } ] [, ...]
    ]
    [ LIMIT { contador | ALL } ]
    [ OFFSET início [ ROW | ROWS ] ]
    [ FETCH { FIRST | NEXT } [ contador ]
        { ROW | ROWS } { ONLY | WITH TIES }
    ]
    [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE }
        [ OF referência_FROM [, ...] ]
        [ NOWAIT | SKIP LOCKED ]
        [...]
    ]

onde item_FROM pode ser um entre:

    [ ONLY ] nome_da_tabela [ * ]
        [ [ AS ] alias
          [ ( alias_de_coluna [, ...] )
          ]
        ]
        [ TABLESAMPLE mé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_FROM tipo_de_junção item_FROM
        { ON condição_de_junção
        | USING ( coluna_de_junção [, ...] )
          [ AS junção_usando_alias ]
        }
    item_FROM NATURAL tipo_de_junção item_FROM
    item_FROM CROSS JOIN item_FROM

e elemento_de_agrupamento pode ser um entre:

    ( )
    expressão
    ( expressão [, ...] )
    ROLLUP ( { expressão
             | ( expressão [, ...] )
             } [, ...]
           )
    CUBE ( { expressão
           | ( expressão [, ...] )
           }
           [, ...]
         )
    GROUPING SETS ( elemento_de_agrupamento [, ...] )

e consulta_WITH é:

    nome_da_consulta_WITH
        [ ( nome_da_coluna [, ...] )
        ]
        AS [ [ NOT ] MATERIALIZED ]
        ( seleção
        | values
        | insert
        | update
        | delete
        | merge
        )
        [ SEARCH { BREADTH | DEPTH } FIRST BY nome_da_coluna [, ...]
            SET search_seq_col_name
        ]
        [ CYCLE nome_da_coluna [, ...]
            SET cycle_mark_col_name
            [ TO cycle_mark_value
              DEFAULT cycle_mark_default
            ]
            USING cycle_path_col_name
        ]

TABLE [ ONLY ] nome_da_tabela [ * ]

Descrição

O comando SELECT recupera linhas de zero ou mais tabelas. O processamento geral do comando SELECT é o seguinte:

  1. 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.)

  2. 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.)

  3. 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.)

  4. 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.

  5. 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.)

  6. 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.)

  7. 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.)

  8. 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.)

  9. 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.)

  10. 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).

Parâmetros

Cláusula 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_recursivo UNION [ 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.

Cláusula 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 ( nome_da_coluna tipo_de_dados [, ... ]). A lista de definição de colunas deve corresponder ao número e aos tipos de dados das colunas retornados pela função.

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ção

Um 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ção, USING (coluna_de_junção [, ...]), ou 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 X RIGHT JOIN LATERAL Y seja sintaticamente válida, na verdade não é permitido que Y faça referência a X.

Cláusula 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.

Cláusula 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.

Cláusula WINDOW

A cláusula opcional WINDOW tem a forma geral

WINDOW nome_da_janela AS ( 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 BY expressão [, ...] ]
[ ORDER BY expressão [ ASC | DESC | USING operador ] [ 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 PRECEDING
deslocamento PRECEDING
CURRENT ROW
deslocamento FOLLOWING
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 deslocamento PRECEDING não é permitido.

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.

Lista 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 nome_da_tabela.* como um atalho para as colunas provenientes apenas dessa tabela. Nesses casos não é possível especificar novos nomes usando o 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.

Nota

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.

Cláusula 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 ( expressão [, ...] ) mantém apenas a primeira linha de cada conjunto de linhas onde as expressões fornecidas são avaliadas como iguais. As expressões 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.

Cláusula UNION

A cláusula UNION tem a forma geral

comando_select UNION [ 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.

Cláusula INTERSECT

A cláusula INTERSECT tem a forma geral

comando_select INTERSECT [ 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.

Cláusula EXCEPT

A cláusula EXCEPT tem a forma geral

comando_select EXCEPT [ 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.

Cláusula ORDER BY

A cláusula opcional ORDER BY tem a forma geral

ORDER BY expressão [ ASC | DESC | USING operador ] [ 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.

Cláusula 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 é:

OFFSET iní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.

Cláusula de bloqueio

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

FOR força_de_bloqueio [ OF referê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.

Cuidado

É 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.

Comando TABLE

O 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.

Exemplos

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.


Conformidade

É claro que o comando SELECT é compatível com o padrão SQL, mas existem algumas extensões e alguns recursos ausentes.

Cláusulas 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.

Listas 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.

Omissão da palavra-chave 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.

Omissão de aliases do sub-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.)

Restrições da cláusula 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.

Chamadas de função no 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 func(...) alias é aproximadamente equivalente a FROM LATERAL (SELECT func(...)) alias. Note que LATERAL é 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.

Espaço de nomes disponível para 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.

Dependências funcionais

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.

Declarações de modificação de dados no WITH

O PostgreSQL permite que INSERT, UPDATE, e DELETE sejam usados nas consultas WITH. Isto não consta no padrão SQL.

Cláusulas fora do padrão

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.