Moh*_*awy 38 postgresql ruby-on-rails ruby-on-rails-3 postgresql-json
试图在带有rails的模式上做区别.
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 >
Run Code Online (Sandbox Code Playgroud)
得到一个错误 PG::UndefinedFunction: ERROR: could not identify an equality operator for type json
在这种情况下,转换为Hstore不是我的选择.有什么工作吗?
poz*_*ozs 55
这背后的原因是,在PostgreSQL(最多9.3)中没有定义相等运算符json(val1::json = val2::json即将始终抛出此异常) - 在9.4中将有一个jsonb类型.
一个解决方法是,您可以将您的json字段投射到text.但这并不能涵盖所有json的平等.f.ex. {"a":1,"b":2}应该等于{"b":2,"a":1},但如果铸造,则不会相等text.
另一种解决方法是(如果您有该表的主键 - 应该是),您可以使用以下DISTINCT ON (<expressions>)表单:
u.profiles.select("DISTINCT ON (profiles.id) profiles.*")
Run Code Online (Sandbox Code Playgroud)
注意:一个已知的警告DISTINCT ON:
DISTINCT ON表达式必须与最左边的ORDER BY表达式匹配.ORDER BY子句通常包含其他表达式,用于确定每个DISTINCT ON组中行的所需优先级.
对不起,我迟到了这个答案,但它可能对其他人有帮助.
据我了解你的查询,你只能得到重复,profiles因为多对多的连接integrations(你用它来确定profiles访问哪个).
因此,您可以使用9.1中的新GROUP 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"
Run Code Online (Sandbox Code Playgroud)
我只删除了DISTINCT你的SELECT条款并添加了GROUP BY.
通过仅引用其中id的内容GROUP BY,您可以利用该新功能,因为所有剩余profiles列都在该ID主键上"功能相关".
不知何故,奇妙地避免了Postgres对依赖列(即json本例中的列)进行等式检查的需要.
该DISTINCT ON解决方案也很大,和你的情况显然足够了,但你不能使用聚合功能,如array_agg它.你可以用这种GROUP BY方法.快乐的时光!:)
小智 5
如果您使用 PG 9.4 ,则使用 JSONB 而不是 JSON 可以解决此问题示例:
-- JSON datatype test
create table t1 (id int, val json);
insert into t1 (id,val) values (1,'{"name":"value"}');
insert into t1 (id,val) values (1,'{"name":"value"}');
insert into t1 (id,val) values (2,'{"key":"value"}');
select * from t1 order by id;
select distinct * from t1 order by id;
-- JSONB datatype test
create table t2 (id int, val jsonb);
insert into t2 (id,val) values (1,'{"name":"value"}');
insert into t2 (id,val) values (1,'{"name":"value"}');
insert into t2 (id,val) values (2,'{"key":"value"}');
select * from t2 order by id;
select distinct * from t2 order by id;
Result of running the above script :
CREATE TABLE
INSERT 0 1
INSERT 0 1
INSERT 0 1
1 | {"name":"value"}
1 | {"name":"value"}
2 | {"key":"value"}
ERROR: could not identify an equality operator for type json
LINE 1: select distinct * from t1 order by id;
^
CREATE TABLE
INSERT 0 1
INSERT 0 1
INSERT 0 1
1 | {"name": "value"}
1 | {"name": "value"}
2 | {"key": "value"}
1 | {"name": "value"}
2 | {"key": "value"}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,PG 成功地在 JSONB 列上暗示了 DISTINCT,而在 JSON 列上却失败了!
还可以尝试以下操作以查看 JSONB 中的实际键是否已排序:
insert into t2 values (3, '{"a":"1", "b":"2"}');
insert into t2 values (3, '{"b":"2", "a":"1"}');
select * from t2;
1 | {"name": "value"}
1 | {"name": "value"}
2 | {"key": "value"}
3 | {"a": "1", "b": "2"}
3 | {"a": "1", "b": "2"}
Run Code Online (Sandbox Code Playgroud)
请注意,'{"b":"2", "a":"1"}' 被插入为 '{"a":"1", "b":"2"}' 因此 PG 将其标识为相同记录 :
select distinct * from t2;
3 | {"a": "1", "b": "2"}
2 | {"key": "value"}
1 | {"name": "value"}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18149 次 |
| 最近记录: |