No podía identificar operador de igualdad de tipo json[] cuando se utiliza la UNIÓN

Estoy tratando de realizar varias consultas en una sola tabla mediante un UNION regla

Tengo dos tablas:

  • proyecto (id, nombre, clavado BOOLEAN)
  • habilidades (m2m a proyectos)

Estoy buscando para obtener primero una matriz de filas que han pinned conjunto para true y llenar el resto con las últimas entradas (pinned conjunto para false)

SELECT
  project.id AS project_id,
  project.name AS project_name,
  array_agg(json_build_object('skill_id', project_skills.id,'name', project_skills.skill)) AS skills
from project
LEFT OUTER JOIN project_skills on project.name = project_skills.project
WHERE project.pinned = true
GROUP BY project_id,project_name

UNION

SELECT
  project.id AS project_id,
  project.name AS project_name,
  array_agg(json_build_object('skill_id', project_skills.id,'name', project_skills.skill)) AS skills
from project
LEFT OUTER JOIN project_skills on project.name = project_skills.project
WHERE project.id != 1 AND project.pinned = false
GROUP BY project_id,project_name
ORDER BY project.create_date DESC LIMIT 5

Al realizar esta consulta , me sale el siguiente error

ERROR:  could not identify an equality operator for type json[]
LINE 7:   array_agg(json_build_object('skill_id', project_skills.id,...

No entiendo este error. Es que falle debido a que su tratando de comparar el json columnas de ambos resultados?

Estoy usando Postgresql 9.4.

InformationsquelleAutor Kannaj | 2017-05-01

2 Kommentare

  1. 51

    Cuando se utiliza un UNION, el DBMS elimina todas las filas duplicadas, y para ello es necesario identificar si dos filas son iguales /idénticos. Esto a su vez significa mirar en cada columna de las dos filas que se está comparando, y decidir si son iguales.

    El mensaje de error que estamos viendo es donde uno de sus columnas se construyen mediante array_agg(json_build_object(...)) que produce un valor de tipo json[], que significa «matriz de json valores». Porque Postgres no sabe cómo comparar dos matrices de JSON valores, no puede decidir si su UNION producido duplicados.

    Si no que realmente preocupa a la eliminación de duplicados, la solución más sencilla es utilizar UNION ALL que se salta este paso.

    Como se señaló en los comentarios, si hacer desea eliminar duplicados, puede convertir los valores a algo que tiene un operador de comparación definido. La mayoría de la solución general es para la conversión a texto (por ejemplo, some_value::text o CAST(some_value as text)) pero para JSON específicamente, usted probablemente querrá el jsonb tipo de, que ignora el formato de la hora de comparar.

    Que pudieras lanzar json a jsonb, o json[] a jsonb[], o en este ejemplo, usted podría construir jsonb directamente con array_agg(jsonb_build_object(...)) en lugar de array_agg(json_build_object(...)).

    • Si UNION es necesita una de las alternativas es para echar a jsonb (de fundición o de la matriz a jsonb[] en consecuencia), para que el operador de igualdad se define. Ver: stackoverflow.com/a/24296054/939860 o stackoverflow.com/a/30520760/939860. (Usted perder el formato original, a pesar de que normalmente es irrelevante.)
    • Tenía el mismo problema y me acabo de convertir el valor en texto usando ::text tanto en el grupo y en el select para facilitar la comparación, se quejó. Fue construir una jerarquía de vistas en un nivel más arriba, acabo de fundición de vuelta a json cuando sea necesario con ::json[]. El Uso De Pg 9.6.
    • Tenía el mismo problema con distinct. No la necesitamos, así que lo sacó.
  2. 4

    Resulta que todo lo que tenía que hacer era usar UNION ALL – supongo que esto ignora tratando de comparar json tipos en las consultas.

    • Este debe ser un comentario a IMSoP la respuesta.
    • de hecho, me di cuenta de la solución antes de que yo pudiera tener la respuesta a este post. acabo de añadir mi respuesta, en lugar de eliminar el post. Acepté su respuesta de todos modos, aunque ya era más útil que la mía

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea