使用UNION时无法识别json []类型的等号运算符

时间:2017-05-01 11:56:47

标签: json postgresql union

我尝试使用UNION规则在单个表上执行多个查询

我有两张桌子:

  • 项目(id,name,pinned BOOLEAN)
  • 技能(m2m to projects)

我希望首先获取pinned设置为true的行数组,并将剩余的行填入最新条目(pinned设为{{1} }})

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

我不明白这个错误。它失败了,因为它试图比较两个结果中的json列吗?

我使用的是Postgres 9.4。

2 个答案:

答案 0 :(得分:41)

当您使用UNION时,DBMS会删除任何重复的行,为此,需要确定两行是否相等/相同。这反过来意味着查看它所比较的​​两行中的每一列,并确定它们是否相等。

您看到的错误消息是使用array_agg(json_build_object(...))生成某个列的列,其中生成类型为json[]的值,这意味着“json值数组”。因为Postgres不知道如何比较两个JSON值数组,所以它无法确定您的UNION是否产生重复。

如果您实际上并不关心删除重复项,最简单的解决方案是使用跳过此步骤的UNION ALL

正如评论中所指出的,如果你想要删除重复项,你可以将值转换为定义了比较运算符的值。最常见的解决方案是转换为文本(例如some_value::textCAST(some_value as text)),但对于JSON,您可能需要the jsonb type,这会在比较时忽略格式。

您可以将json投放到jsonb,或json[]投放到jsonb[],或者在此示例中,您可以直接使用jsonb构建array_agg(jsonb_build_object(...))而不是array_agg(json_build_object(...))

答案 1 :(得分:2)

原则上我所要做的就是使用UNION ALL - 我想这会忽略尝试在查询中比较json类型。