46

レールを使用したモードで明確にしようとしています。

2.1.1 :450 > u.profiles.select("profiles.*").distinct


Profile Load (0.9ms)  SELECT DISTINCT profiles.* FROM "profiles" INNER JOIN "integration_profiles" ON "profiles"."id" = "integration_profiles"."profile_id" INNER JOIN "integrations" ON "integration_profiles"."integration_id" = "integrations"."id" WHERE "integrations"."user_id" = $1  [["user_id", 2]]
PG::UndefinedFunction: ERROR:  could not identify an equality operator for type json
LINE 1: SELECT DISTINCT profiles.* FROM "profiles" INNER JOIN "integ...
                        ^
: SELECT DISTINCT profiles.* FROM "profiles" INNER JOIN "integration_profiles" ON "profiles"."id" = "integration_profiles"."profile_id" INNER JOIN "integrations" ON "integration_profiles"."integration_id" = "integrations"."id" WHERE "integrations"."user_id" = $1
ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR:  could not identify an equality operator for type json
LINE 1: SELECT DISTINCT profiles.* FROM "profiles" INNER JOIN "integ...
                        ^
: SELECT DISTINCT profiles.* FROM "profiles" INNER JOIN "integration_profiles" ON "profiles"."id" = "integration_profiles"."profile_id" INNER JOIN "integrations" ON "integration_profiles"."integration_id" = "integrations"."id" WHERE "integrations"."user_id" = $1
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/rack-mini-profiler-0.9.1/lib/patches/sql_patches.rb:109:in `prepare'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/rack-mini-profiler-0.9.1/lib/patches/sql_patches.rb:109:in `prepare'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:834:in `prepare_statement'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:795:in `exec_cache'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:139:in `block in exec_query'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/abstract_adapter.rb:442:in `block in log'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activesupport-4.0.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/abstract_adapter.rb:437:in `log'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:137:in `exec_query'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:908:in `select'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/abstract/database_statements.rb:32:in `select_all'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/querying.rb:36:in `find_by_sql'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/relation.rb:585:in `exec_queries'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/association_relation.rb:15:in `exec_queries'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/relation.rb:471:in `load'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/relation.rb:220:in `to_a'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/relation.rb:573:in `inspect'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/railties-4.0.4/lib/rails/commands/console.rb:90:in `start'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/railties-4.0.4/lib/rails/commands/console.rb:9:in `start'
    from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/railties-4.0.4/lib/rails/commands.rb:62:in `<top (required)>'
    from bin/rails:4:in `require'
    from bin/rails:4:in `<main>'2.1.1 :451 > 

エラーの取得PG::UndefinedFunction: ERROR: could not identify an equality operator for type json

この場合、Hstore への変換はオプションではありません。回避策はありますか?

4

4 に答える 4

67

この背後にある理由は、PostgreSQL (9.3 まで) では等値演算子が定義されていないためですjson(つまりval1::json = val2::json、常にこの例外がスローされます)。9.4 ではjsonb型に対して 1 つ存在します。

json1 つの回避策は、フィールドを にキャストできることtextです。しかし、それはすべての json 等式をカバーするわけではありません。f.ex。{"a":1,"b":2}と等しいはずですが{"b":2,"a":1}、 にキャストされた場合は等しくなりませんtext

別の回避策は(そのテーブルの主キーがある場合-そうあるべきです)、次のDISTINCT ON (<expressions>)形式を使用できます:

u.profiles.select("DISTINCT ON (profiles.id) profiles.*")

: に関する既知の警告の 1 つDISTINCT ON:

DISTINCT ON 式は、一番左の ORDER BY 式と一致する必要があります。通常、ORDER BY 句には、各 DISTINCT ON グループ内の行の優先順位を決定する追加の式が含まれます。

于 2014-05-07T07:57:20.397 に答える
10

この回答に遅れて申し訳ありませんが、他の人に役立つかもしれません。

私があなたのクエリを理解しているようprofilesに、多対多の結合(アクセスintegrations先を決定するために使用している)のために、重複の可能性しかありません。profiles

そのため、9.1GROUP BY以降の新しい機能を使用できます。

GROUP BY が存在する場合、集計関数内を除き、グループ化されていない列を SELECT リスト式で参照することは無効です。または、グループ化されていない列がグループ化された列に機能的に依存している場合を除きます。グループ化されていない列。グループ化された列 (またはそのサブセット) が、グループ化されていない列を含むテーブルの主キーである場合、機能的な依存関係が存在します。

したがって、あなたの場合、Ruby にクエリを作成させることができます (申し訳ありませんが、使用している Ruby 構文はわかりません)...

SELECT profiles.* 
FROM "profiles" 
  INNER JOIN "integration_profiles" ON "profiles"."id" = "integration_profiles"."profile_id" 
  INNER JOIN "integrations" ON "integration_profiles"."integration_id" = "integrations"."id" 
WHERE "integrations"."user_id" = $1
GROUP BY "profiles"."id"

私はDISTINCTあなたのSELECT句から を削除し、 を追加しただけGROUP BYです。

の のみを参照することidGROUP BY、残りのすべてのprofiles列がその id プライマリ キーに「機能的に依存」するため、その新しい機能を利用できます。

どういうわけか、Postgres が依存する列 (つまりjson、この場合はあなたの列) で等価性チェックを行う必要がなくなります。

DISTINCT ONソリューションも素晴らしく、あなたのケースでは明らかに十分ですが、それのような集約関数を使用することはできませんarray_agg。このGROUP BYアプローチでできます。幸せな日々!:)

于 2015-08-07T11:48:42.683 に答える
2

ええ、残念ながらpostgresjsonは平等を実装していませんが、実装jsonbしています。したがって、json列をに移行しjsonbても問題なく動作するはずです。

于 2019-07-03T09:50:01.600 に答える