UNION
ルールを使用して、単一のテーブルで複数のクエリを実行しようとしています
2つのテーブルがあります。
私は最初に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を使用しています。
UNION
を使用すると、DBMSは重複行を削除します。これを行うには、2つの行が等しい/同一であるかどうかを識別する必要があります。これは、比較している2行の各列を見て、それらが等しいかどうかを判断することを意味します。
表示されているエラーメッセージは、array_agg(json_build_object(...))
を使用して列の1つが作成され、_json[]
_型の値を生成します。これは「json値の配列」を意味します。 PostgresはJSON値の2つの配列を比較する方法を知らないため、UNION
が重複を生成したかどうかを判断できません。
実際に重複を削除する必要がない場合、最も簡単な解決策は_UNION ALL
_を使用することで、この手順はスキップされます。
コメントで指摘されているように、do重複を削除したい場合、比較演算子が定義されている値に値をキャストできます。最も一般的な解決策はテキスト(たとえば_some_value::text
_またはCAST(some_value as text)
)にキャストすることですが、JSONの場合は特に jsonb
type が必要です。これは比較時にフォーマットを無視します。
json
をjsonb
に、または_json[]
_を_jsonb[]
_にキャストできます。または、この例では、array_agg(jsonb_build_object(...))
ではなくarray_agg(json_build_object(...))
で直接jsonb
をビルドできます。
私がしなければならなかったことは、UNION ALL
-これは、クエリ間でjson
型を比較しようとすることを無視すると思います。