Se eu uso array_agg
para coletar nomes, eu os separo por vírgulas, mas caso haja um null
valor, nulo também é considerado um nome no agregado. Por exemplo :
SELECT g.id,
array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END) canonical_users,
array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END) non_canonical_users
FROM groups g
GROUP BY g.id;
ele retorna em ,Larry,Phil
vez de apenas Larry,Phil
(no meu 9.1.2, ele mostra NULL,Larry,Phil
). como neste violino
Em vez disso, se eu usar string_agg()
, ele mostra apenas os nomes (sem vírgulas vazias ou nulos) como aqui
O problema é que Postgres 8.4
instalei no servidor e string_agg()
não funciona lá. Existe alguma maneira de fazer array_agg funcionar de forma semelhante a string_agg ()?
Respostas:
SQL Fiddle
Ou, mais simples e pode ser mais barato, usando o
array_to_string
que elimina nulos:SQL Fiddle
fonte
array_to_string(array_agg(...))
você também pode usarstring_agg
.Com o postgresql-9.3 pode-se fazer isso;
Atualização : com postgresql-9.4;
fonte
Ao resolver a questão geral de remover nulos de agregados de array, há duas maneiras principais de atacar o problema: fazendo array_agg (unnest (array_agg (x)) ou criando um agregado personalizado.
O primeiro tem o formato mostrado acima :
O segundo:
Chamar o segundo é (naturalmente) um pouco mais bonito do que o primeiro:
fonte
Estou adicionando isso, embora este tópico seja bastante antigo, mas encontrei um truque bacana que funciona muito bem em matrizes pequenas. Ele roda em Postgres 8.4+ sem bibliotecas ou funções adicionais.
O
array_to_string()
método realmente elimina os nulos.fonte
Se você está procurando uma resposta moderna para a questão geral de como remover um NULL de uma matriz , é:
Eu estava especificamente curioso sobre o desempenho e queria comparar isso com a melhor alternativa possível:
Fazer um teste pgbench provou (com alta confiança) que array_remove () é um pouco mais do que duas vezes mais rápido . Eu fiz meu teste em números de precisão dupla com uma variedade de tamanhos de array (10, 100 e 1000 elementos) e NULLs aleatórios entre eles.
fonte
Como foi sugerido nos comentários, você pode escrever uma função para substituir os nulos em uma matriz, no entanto, como também apontado no tópico vinculado aos comentários, isso prejudica a eficiência da função de agregação se você tiver que criar um agregado , divida-o e, em seguida, agregue-o novamente.
Acho que manter nulos na matriz é apenas um recurso (talvez indesejado) de Array_Agg. Você pode usar subconsultas para evitar isso:
SQL FIDDLE
fonte
É muito simples, basta primeiro criar um novo operador - (menos) para o texto [] :
E simplesmente subtraia a matriz [null]:
Isso é tudo:
{S, N}
fonte
array_agg(x) FILTER (WHERE x is not null)
parece muito mais fácil: dbfiddle.uk/… e você realmente não precisa de sua própria função, você pode simplesmente usararray_remove()
dbfiddle.uk/…Uma questão maior é por que puxar todos os combos de usuário / grupo de uma vez. Garantido que sua interface do usuário não pode lidar com todos esses dados. Adicionar paginação a dados superdimensionados também é uma má ideia. Faça com que seus usuários filtrem o conjunto antes de ver os dados. Certifique-se de que o conjunto de opções JOIN esteja na lista para que eles possam filtrar por desempenho, se quiserem. Às vezes, 2 consultas deixam os usuários mais felizes se ambos forem rápidos.
fonte