UNION

2017-05-01 6 views
6

を使用しているとき、私はUNIONルールにUNION

を使用して、単一のテーブルの上に複数のクエリを実行しようとしています[]型のJSONの等価演算子をcouldntのを識別私は2つのテーブルがあります。

  • プロジェクト(IDを、名前、固定BOOLEAN)
  • スキル(プロジェクトにM2M)

私が最初にpinnedセットを持つ行の配列を取得していますよこのクエリを実行する場合、私は以下のエラー

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

を取得し、私はこのことを理解していない

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 

を(falseからpinnedセット)最新のエントリで残りを埋めますエラー。両方の結果からjson列を比較しようとしているので失敗していますか?

私はPostgres 9.4を使用しています。

答えて

8

あなたがUNIONを使用する場合、DBMSは任意の重複行を削除し、そうするためには、それは2つの行が同じ/等しいかどうかを確認する必要があります。これは、比較している2つの行の各列を調べ、それらが等しいかどうかを判断することを意味します。

表示されるエラーメッセージは、array_agg(json_build_object(...))を使用して列の1つが作成され、json[]という値を生成します。これは「json値の配列」を意味します。 PostgresはJSON値の2つの配列を比較する方法を知らないので、UNIONが重複を生成したかどうかを判断できません。

重複の削除に実際に気にしない場合、最も簡単な解決策は、この手順をスキップするUNION ALLを使用することです。

+4

@Kunkka: 'UNION'が*必要な場合、* 1つの方法は' jsonb'にキャストする(または配列を 'jsonb []'にキャストする)ことです。等価演算子が定義されます。参照:http://stackoverflow.com/a/24296054/939860またはhttp://stackoverflow.com/a/30520760/939860。 (元の形式は失われていますが、これは通常は無関係です) –

+0

同じ問題がありました。私はグループ内で ':text'を使用してテキストに値をキャストしました。ビューの階層構造をさらにレベルアップしましたので、 ':: json []'で必要なときにjsonにキャストし直しました。 Pg 9.6の使用。 –

1

私がしなければならなかったのは、UNION ALLでした。これは、クエリ全体でjsonのタイプを比較しようとして無視していると思います。

+0

これはIMSoPの答えに対するコメントになるはずです。 –

+0

@ErwinBrandstetter私はこの記事の答えを得る前に、実際に解決策を見つけました。私はちょうど私の答えを投稿を削除する代わりに追加しました。 – Kannaj