Desafortunadamente, no hay ninguna disposición en la sintaxis SQL para decir "todas las columnas excepto esta columna" . Puede lograr su objetivo deletreando la lista restante de columnas en una expresión de tipo fila :
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Esa es la abreviatura de la forma más explícita: . ROW
(b.col1, b.col2, b.col3)
Sin embargo, los nombres de las columnas no se conservan en las expresiones de tipo fila. Obtiene nombres de clave genéricos en el objeto JSON de esta manera. Veo 3 opciones para preservar los nombres de columna originales:
1. Transmitir al tipo registrado
Transmitir a un tipo de fila conocido (registrado). Se registra un tipo para cada tabla o vista existente o con una CREATE TYPE
declaración explícita . Puede usar una tabla temporal para una solución ad-hoc (dura toda la sesión):
CREATE TEMP TABLE x (col1 int, col2 text, col3 date); -- use adequate data types!
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)::x) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
2. Use una subselección
Use una subselección para construir una tabla derivada y hacer referencia a la tabla como un todo . Esto también lleva nombres de columna. Es más detallado, pero no necesita un tipo registrado:
SELECT a.id, a.name
, json_agg((SELECT x FROM (SELECT b.col1, b.col2, b.col3) AS x)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
SELECT a.id, a.name
, json_agg(json_build_object('col1', b.col1, 'col2', b.col2, 'col3', b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Relacionado:
Similar para jsonb
con las funciones respectivas jsonb_agg()
y jsonb_build_object()
.
Para Postgres 9.5 o posterior también vea la respuesta de a_horse con una nueva variante de sintaxis más corta: Postgres agregó el operador menos -
parajsonb
decir "todas las teclas excepto esta clave" .
Dado que Postgres 10 "excepto varias claves" se implementa con el mismo operador tomando text[]
como segundo operando, como comentó mlt.
Comenzando con 9.6, simplemente puede usar
-
para eliminar una clave de un JSONB:to_jsonb(b)
convertirá la fila completa y- 'item_id'
luego eliminará la clave con el nombreitem_id
del resultado que se agrega.fuente
json_agg
función:function json_agg(record) does not exist
En realidad, puede hacerlo sin grupo, utilizando subconsultas
devoluciones
Este artículo de John Atten es realmente interesante y tiene más detalles.
fuente
He descubierto que es mejor crear el JSON y luego agregarlo. p.ej
Tenga en cuenta que esto se puede hacer como una subconsulta si no le gustan los CTE (o si tiene problemas de rendimiento debido a su uso).
Tenga en cuenta también que si va a hacer esto mucho, puede ser beneficioso crear una función para ajustar los pares clave-valor para que el código se vea más limpio. Pasarías tu función (por ejemplo)
'ecks', 'x'
y volvería"ecks": "x"
.fuente
Si bien todavía no hay forma de hacer nada sobre la selección de todas las columnas excepto un bit, puede usar
json_agg(to_json(b.col_1, b.col_2, b.col_3 ...))
para obtener una matriz json de jsons cada una en el formato{"col_1":"col_1 value", ...}
.Entonces la consulta se vería así:
y devolvería filas como:
(Ahora estoy en Postgres 9.5.3 y no estoy 100% seguro de cuándo se agregó este soporte).
fuente
Puedes usar
json_build_object
asífuente