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

Posted

技术标签:

【中文标题】使用 UNION 时无法识别 json[] 类型的相等运算符【英文标题】:Couldnt identify equality operator of type json[] when using UNION 【发布时间】:2017-09-28 20:19:06 【问题描述】:

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

我有两张桌子:

项目(id、名称、固定布尔值) 技能(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

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

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

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

我使用的是 Postgres 9.4。

【问题讨论】:

【参考方案1】:

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

【讨论】:

这应该是对 IMSoP 答案的评论。 @ErwinBrandstetter 在我得到这篇文章的答案之前,我实际上已经想出了解决方案。我只是添加了我的答案而不是删除帖子。不过我还是接受了他的回答,因为它比我的更有帮助【参考方案2】:

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

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

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

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

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

【讨论】:

@Kunkka: 如果UNION需要,另一种选择是将数组转换为jsonb(或相应地将数组转换为jsonb[]),其中相等运算符被定义为。请参阅:***.com/a/24296054/939860 或 ***.com/a/30520760/939860。 (不过,您会丢失原始格式 - 这通常是无关紧要的。) 有同样的问题,我只是在 group by 和 select 中使用 ::text 将值转换为文本,以方便它抱怨的比较。正在构建视图层次结构,因此在更高级别上,我只是在需要时使用::json[] 转换回 json。使用第 9.6 页。 使用distinct 时遇到同样的问题。不需要,所以我把它拿出来了。

以上是关于使用 UNION 时无法识别 json[] 类型的相等运算符的主要内容,如果未能解决你的问题,请参考以下文章

如何在 json 模式中表示 sum/union 类型

实现通用链接时无法识别 JSON 文件

Webstorm 中的 ESLint 无法识别 React 类型

UNION 类型 text 和 bigint 无法匹配

在 VS Code 上运行 Flask 应用程序时无法识别 launch.json 中的环境变量

使用npm twit将图像上传到Twitter时“媒体类型无法识别”