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

Kan*_*naj 27 postgresql union json

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

我有两张桌子:

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

我希望首先得到一组pinned设置为的行,true并用最新的条目填充剩余的(pinned设置为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
Run Code Online (Sandbox Code Playgroud)

执行此查询时,我得到以下错误

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

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

我正在使用Postgres 9.4.

IMS*_*SoP 50

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

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

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

正如注释中所指出的,如果您确实想要删除重复项,则可以将值转换为已定义比较运算符的值.最普遍的解决办法是转换为文本(例如some_value::textCAST(some_value as text)),但JSON明确你可能想jsonb类型,比较时将忽略格式化.

你可以投jsonjsonb,或者json[]jsonb[],或在这个例子中,你可以建立jsonb直接array_agg(jsonb_build_object(...))而不是array_agg(json_build_object(...)).

  • @Kunkka:如果*UNION`是*需要*一个替代方案是转换为`jsonb`(或相应地将数组转换为`jsonb []`),为此定义了相等运算符.请参阅:http://stackoverflow.com/a/24296054/939860或http://stackoverflow.com/a/30520760/939860.(但是你失去了原始格式 - 这通常是无关紧要的.) (4认同)
  • 使用“distinct”也有同样的问题。不需要,所以我就把它拿出来了。 (2认同)

Kan*_*naj 11

原来我所要做的就是使用UNION ALL- 我想这忽略了尝试比较json跨查询的类型。

  • @ErwinBrandstetter 在得到这篇文章的答案之前,我实际上已经找到了解决方案。我只是添加了我的答案而不是删除帖子。不过我还是接受了他的回答,因为它比我的更有帮助 (3认同)