Suponha que eu tenha as tabelas a (com coluna a1) e b (com colunas b1 e b2) e execute uma junção externa esquerda
SELECT *
FROM a LEFT OUTER JOIN b
ON a.a1 = b.b1
Então b1 e b2 serão NULL onde um valor de a1 não tem valor correspondente de b1.
Posso fornecer um valor padrão para b2, em vez de NULL? Observe que COALESCE não funcionará aqui, porque não quero que o valor padrão substitua NULLs em potencial em b2, onde há um valor de b1 correspondente a a1.
Ou seja, com a e b como
CREATE TABLE a (a1)
AS VALUES (1),
(2),
(3) ;
CREATE TABLE b (b1,b2)
AS VALUES (1, 10),
(3, null) ;
a1 b1 | b2
--- --------
1 1 | 10
2 3 | NULL
3
e um padrão para b2 de, digamos, 100, quero obter o resultado
a1 | b1 | b2
---------------
1 | 1 | 10
2 | NULL | 100
3 | 3 | NULL
Neste caso simples, eu poderia fazê-lo "manualmente", verificando se b1 é NULL na saída. Essa é a melhor opção em geral, ou existe uma maneira mais padrão e mais limpa?
Acho COALESCE muito útil nesse caso. Ele retornará o primeiro valor não NULL de uma lista:
Depois que @ypercube identificou corretamente um problema em que minha resposta não correspondia à pergunta. aqui está a correção dele:
A resposta original a essa pergunta não foi explicada, então vamos tentar outra vez.
Usando uma
CASE
expressãoUsando esse método, exploramos que temos outro valor em uma coluna diferente que
IS NOT NULL
, nesse caso,b.b1
se esse valor for nulo, saberemos que a junção falhou.Isso funcionará totalmente e gerará exatamente a coisa que você deseja.
Usando um sub-SELECT
Não use este método, é uma ideia de construção. Continue lendo.
Se não tivermos nenhuma
NOT NULL
coluna que possamos explorar assim, precisamos de algo para criar uma coluna que possa funcionar dessa maneira para nós ...Usando uma comparação de linhas
Ainda mais fácil forçar um valor falso para o qual podemos comparar é comparar a linha. No PostgreSQL, a linha tem um valor pelo nome da tabela. Por exemplo,
SELECT foo FROM foo
retorna uma linha do tipofoo
(que é um tipo de linha), da tabelafoo
. Aqui testamos para ver se essa ROW é nula. Isso funcionará desde que cada colunaIS NOT NULL
. E, se todas as colunasIS NULL
da sua tabela, você está apenas trollando.Como alternativa aos valores das colunas, pode-se querer usar uma linha padrão nas linhas não correspondentes
Usando o dialeto tsql com base no comentário: Adicionei uma tag para indicar que aceitaria uma resposta específica do Postgres. Ainda assim, o SQL padrão seria o preferido, se possível .
Dados de teste
Consulta básica
Resultado básico
Você pode usar essa abordagem para uma abordagem mais baseada em conjuntos, tratando os padrões como substitutos para a diferença nos dois conjuntos.
Aqui está um exemplo mais avançado em que os ids pares/ímpares de têm diferentes linhas
a
padrão .b
Consulta avançada
Resultado avançado
O OP pediu uma alternativa ao uso do método case / coalesce / ifnull típico para substituir valores nulos, especificando um 'valor padrão' diferente para junções à esquerda em vez de nulo. Esta é uma solicitação válida, pois pode ser complicada se o campo for usado repetidamente ou em cálculos complexos na consulta ou se você quiser diferenciar entre o sinal 'linha não existe na tabela unida' e o resultado 'linha existe, mas esse campo é nulo' . A resposta correta aqui é "não, esse recurso não existe".