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 vão realmente para a saída.
O tipo mais simples de lista de seleção é o *, que emite todas as colunas produzidas pela expressão de tabela. De outra forma, a lista de seleção é uma lista separada por vírgulas de expressões de valor (conforme definido na Seção 4.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 verdadeiros das colunas das tabelas referenciadas na cláusula FROM, ou aliases dados a estas colunas conforme explicado na Seção 7.2.1.2. O espaço de nomes disponível na lista de seleção é o mesmo da cláusula WHERE, a não ser que seja utilizado agrupamento e, neste caso, passa a ser o mesmo da cláusula HAVING.
Quando mais de uma tabela possui uma coluna com o mesmo nome, o nome da tabela deve ser fornecido também, como em:
SELECT tbl1.a, tbl2.a, tbl1.b FROM ...
Ao se trabalhar com várias tabelas, também pode ser útil solicitar todas as colunas de uma determinada tabela:
SELECT tbl1.*, tbl2.a FROM ...
(Consulte também a Seção 7.2.2)
Se for utilizada uma expressão de valor arbitrária na lista de seleção, esta expressão adiciona, conceitualmente, uma nova coluna virtual à tabela retornada. A expressão de valor é avaliada uma vez para cada linha do resultado, com os valores da linha substituídos nas referências a coluna. Porém, as expressões da lista de seleção não precisam referenciar nenhuma coluna da expressão de tabela da cláusula FROM; podem ser, inclusive, expressões aritméticas constantes, por exemplo.
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 classificação e o aplicativo 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 a colunas simples, é o nome da coluna referenciada. Para chamadas de função, é o nome da função. Para expressões complexas o sistema gera um nome genérico.
Nota: Aqui, o nome dado à coluna de saída é diferente do nome dado na cláusula FROM (consulte a Seção 7.2.1.2). Na verdade, este processo permite mudar o nome da mesma coluna duas vezes, mas o nome escolhido na lista de seleção é o passado adiante.
Após a lista de seleção ser processada, a tabela resultante pode opcionalmente estar sujeita à remoção das linhas duplicadas. A palavra chave DISTINCT deve ser escrita logo após o SELECT para especificar esta funcionalidade:
SELECT DISTINCT lista_de_seleção ...
(Em vez de DISTINCT pode ser utilizada a palavra ALL para especificar o comportamento padrão de manter todas as linhas)
Como é óbvio, duas linhas são consideradas distintas quando têm pelo menos uma coluna diferente. Os valores nulos são considerados iguais nesta comparação.
Como alternativa, uma expressão arbitrária pode determinar quais linhas devem ser consideradas distintas:
SELECT DISTINCT ON (expressão [, expressão ...]) lista_de_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. Deve ser observado que a "primeira linha" de um conjunto é imprevisível, a não ser que a consulta seja ordenada por um número suficiente de colunas para garantir a ordem ú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 faz 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 fácil.