Estou tentando conseguir algo como LEFT JOIN
com a função de matriz unnest()
. Eu quero que a consulta retorne uma linha com um valor nulo se a matriz estiver vazia. Portanto, usando uma CASE
construção, eu queria passar um array falso com um único elemento nulo se o array de origem estiver vazio, mas não funciona como esperado:
Consulta 1
select element
from (
select array['a']::text[] as arr --< single non-null element
) sub, unnest(
(
case when array_length(sub.arr, 1) <= 0 then (array[null])::text[]
else sub.arr
end
)
) element
-- returns 1 row with element = "a"
Consulta 2
select element
from (
select array[]::text[] as arr --< empty array
) sub, unnest(
(
case when array_length(sub.arr, 1) <= 0 then (array[null])::text[]
else sub.arr
end
)
) element
-- returns 0 rows (should return 1 row with element = NULL?)
Consulta 3
select element
from (
select array[null]::text[] as arr --< single null element
) sub, unnest(
(
case when array_length(sub.arr, 1) <= 0 then (array[null])::text[]
else sub.arr
end
)
) element
-- return single row with element = NULL
Acabei de descobrir que select array_length(array[]::text[], 1)
retorna NULL
- minha pergunta é por quê?
Para citar Tom Lane no tópico "Should array_length () Return NULL" em pgsql-hackers :
Difícil dizer se
array_length()
deve retornarNULL
ou0
para uma dimensão de array vazia...Solução
Você pode inverter a lógica e processar a matriz de origem original somente se o comprimento for
>= 1
:Retorna pelo menos uma linha para cada linha de origem.
Ou, muito mais simples , use um real
LEFT JOIN
(a vírgula em suaFROM
cláusula é uma notação curta paraCROSS JOIN
):Isso preenche valores NULL automaticamente para as colunas da tabela correta se nenhuma correspondência for encontrada. Exatamente o que você está tentando alcançar.
Relacionado:
db<>mexa aqui