Si utilizo array_agg
para recopilar nombres, obtengo mis nombres separados por comas, pero en caso de que haya un null
valor, ese nulo también se toma como un nombre en el agregado. Por ejemplo :
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;
devuelve en ,Larry,Phil
lugar de solo Larry,Phil
(en mi 9.1.2, se muestra NULL,Larry,Phil
). como en este violín
En cambio, si lo uso string_agg()
, me muestra solo los nombres (sin comas vacías o nulos) como aquí
El problema es que lo he Postgres 8.4
instalado en el servidor y string_agg()
no funciona allí. ¿Hay alguna forma de hacer que array_agg funcione de manera similar a string_agg ()?
Respuestas:
Violín SQL
O, más simple y puede ser más económico, usando
array_to_string
que elimina los nulos:Violín SQL
fuente
array_to_string(array_agg(...))
también podría usarstring_agg
.Con postgresql-9.3 uno puede hacer esto;
Actualizar : con postgresql-9.4;
fuente
Para resolver la cuestión general de eliminar nulos de los agregados de matrices, hay dos formas principales de atacar el problema: haciendo array_agg (unnest (array_agg (x)) o creando un agregado personalizado.
El primero es de la forma que se muestra arriba :
El segundo:
Llamar al segundo es (naturalmente) un poco más agradable que el primero:
fuente
Estoy agregando esto a pesar de que este hilo es bastante antiguo, pero encontré este ingenioso truco que funciona bastante bien en arreglos pequeños. Se ejecuta en Postgres 8.4+ sin bibliotecas o funciones adicionales.
En
array_to_string()
realidad, el método elimina los nulos.fuente
Si está buscando una respuesta moderna a la pregunta general de cómo eliminar un NULL de una matriz , es:
Tenía especial curiosidad por el rendimiento y quería compararlo con la mejor alternativa posible:
Al hacer una prueba pgbench se demostró (con alta confianza) que array_remove () es un poco más del doble de rápido . Hice mi prueba en números de doble precisión con una variedad de tamaños de matriz (10, 100 y 1000 elementos) y NULL aleatorios en el medio.
fuente
Como se sugirió en los comentarios, puede escribir una función para reemplazar nulos en una matriz, sin embargo, como también se señaló en el hilo vinculado en los comentarios, este tipo de derrota la eficiencia de la función agregada si tiene que crear una agregación , divídalo y luego vuelva a agregarlo.
Creo que mantener nulos en la matriz es solo una característica (quizás no deseada) de Array_Agg. Puede usar subconsultas para evitar esto:
Violín SQL
fuente
Es muy simple, primero que nada cree un nuevo operador - (menos) para el texto [] :
Y simplemente reste la matriz [nulo]:
Eso es todo:
{S, N}
fuente
array_agg(x) FILTER (WHERE x is not null)
parece mucho más fácil: dbfiddle.uk/… y realmente no necesita su propia función, simplemente puede usararray_remove()
dbfiddle.uk/…Una pregunta más importante es por qué extraer todos los combos de usuario / grupo a la vez. Garantizado que su interfaz de usuario no puede manejar todos esos datos. Agregar paginación a datos de gran tamaño también es una mala idea. Haga que sus usuarios filtren el conjunto antes de que vean los datos. Asegúrese de que su conjunto de opciones JOIN esté en la lista para que puedan filtrar el rendimiento si así lo desean. A veces, 2 consultas hacen que los usuarios estén más contentos si ambas son rápidas.
fuente