我尝试使用UNION
规则在单个表上执行多个查询
我有两张桌子:
我希望首先获取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。
答案 0 :(得分:41)
当您使用UNION
时,DBMS会删除任何重复的行,为此,需要确定两行是否相等/相同。这反过来意味着查看它所比较的两行中的每一列,并确定它们是否相等。
您看到的错误消息是使用array_agg(json_build_object(...))
生成某个列的列,其中生成类型为json[]
的值,这意味着“json值数组”。因为Postgres不知道如何比较两个JSON值数组,所以它无法确定您的UNION
是否产生重复。
如果您实际上并不关心删除重复项,最简单的解决方案是使用跳过此步骤的UNION ALL
。
正如评论中所指出的,如果你做想要删除重复项,你可以将值转换为定义了比较运算符的值。最常见的解决方案是转换为文本(例如some_value::text
或CAST(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
类型。