4.3. Listas de seleção

Conforme foi mostrado na seção anterior, a expressão de tabela do comando SELECT constrói uma tabela virtual intermediária, possivelmente por meio da combinação de tabelas, visões, eliminação de linhas, agrupamento, etc. Esta tabela é finalmente passada adiante para ser processada pela lista de seleção. A lista de seleção determina quais colunas da tabela intermediária fazem realmente parte da saída.

4.3.1. Itens da lista de seleção

O tipo mais simples de lista de seleção é o *, o qual emite todas as colunas produzidas pela expressão de tabela. Senão, a lista de seleção é uma lista separada por vírgulas de expressões de valor (conforme definido na Seção 1.2). Por exemplo, esta pode ser uma lista de nomes de colunas:

SELECT a, b, c FROM ...

Os nomes das colunas a, b e c podem ser os nomes de verdade das colunas das tabelas referenciadas na cláusula FROM, ou aliases destas colunas conforme explicado na Seção 4.2.1.2. O espaço de nome disponível na lista de seleção é o mesmo da cláusula WHERE, a não ser que o agrupamento seja utilizado, caso em que passa a ser o mesmo da cláusula HAVING.

Se mais de uma tabela possuir uma coluna com o mesmo nome, o nome da tabela também deve ser fornecido, como em:

SELECT tbl1.a, tbl2.b, tbl1.c FROM ...

(Veja também a Seção 4.2.2.)

Se uma expressão de valor arbitrária for utilizada na lista de seleção, conceitualmente uma nova coluna virtual é adicionada à tabela retornada. A expressão de valor é avaliada uma vez para cada linha retornada, com os valores da linha substituídos nas referências a colunas. Porém, a expressão da lista de seleção não precisa referenciar nenhuma coluna da expressão de tabela da cláusula FROM; podem ser, inclusive, expressões aritméticas constantes, por exemplo.

4.3.2. Rótulos de coluna

Podem ser atribuídos nomes para as entradas da lista de seleção para processamento posterior. Neste caso "processamento posterior" é uma especificação opcional de ordenação e a aplicação cliente (por exemplo, os títulos das colunas para exibição). Por exemplo:

SELECT a AS valor, b + c AS soma FROM ...

Se nenhum nome de coluna de saída for especificado utilizando AS, o sistema atribui um nome padrão. Para referências simples a colunas é o nome da coluna referenciada. Para chamadas de função é o mesmo nome da função. Para expressões complexas o sistema gera um nome genérico.

Nota: A nomeação das colunas de saída neste caso é diferente daquela feita na cláusula FROM (veja a Seção 4.2.1.2). Este duto na verdade permite renomear a mesma coluna duas vezes, mas o nome escolhido na lista de seleção é que será passado adiante.

4.3.3. DISTINCT

Após a lista de seleção ser processada, a tabela resultante pode opcionalmente estar sujeita a remoção das linhas duplicadas. A palavra chave DISTINCT deve ser escrita logo após o SELECT para ativar esta funcionalidade:

SELECT DISTINCT lista_seleção ...

(Em vez de DISTINCT a palavra ALL pode ser utilizada para selecionar o comportamento padrão de manter todas as linhas)

Como é óbvio, duas linhas são consideradas distintas quando tiverem pelo menos uma coluna diferente. Os valores nulos são considerados iguais nesta comparação.

Como alternativa, uma expressão arbitrária pode ser utilizada para determinar quais linhas devem ser consideradas distintas:

SELECT DISTINCT ON (expressão [, expressão ...]) lista_seleção ...

Neste caso expressão é uma expressão de valor arbitrária avaliada para todas as linhas. Um conjunto de linhas para as quais todas as expressões são iguais são consideradas duplicadas, e somente a primeira linha do conjunto é mantida na saída. Observe que a "primeira linha" de um conjunto não pode ser predita, a não ser que a consulta seja ordenada por um número suficiente de colunas para garantir a ordenação única das linhas que chegam no filtro DISTINCT (o processamento de DISTINCT ON ocorre após a ordenação do ORDER BY).

A cláusula DISTINCT ON não é parte do padrão SQL, sendo algumas vezes considerada um estilo ruim devido à natureza potencialmente indeterminada de seus resultados. Utilizando-se adequadamente GROUP BY e subconsultas no FROM esta construção pode ser evitada, mas geralmente é a alternativa mais conveniente.