sql – 加入相同的表两次条件
在某些情况下,如果有多个连接具有相同的表,则ActiveRecord会设置别名表名称.我被困在这种连接包含范围(使用’merge’)的情况下.
我有多对多的关系:
一个帖子通过access_levels有很多用户,反之亦然. 两者,用户模型和Post模型共享相同的关系: has_many:access_levels,– > {merge(AccessLevel.valid)} AccessLevel模型的范围如下所示: # v1 scope :valid,-> { where("(valid_from IS NULL OR valid_from < :now) AND (valid_until IS NULL OR valid_until > :now)",:now => Time.zone.now) } # v2 # scope :valid,-> { # where("(#{table_name}.valid_from IS NULL OR #{table_name}.valid_from < :now) AND (#{table_name}.valid_until IS NULL OR #{table_name}.valid_until > :now)",:now => Time.zone.now) # } 我想这样打电话给sth: Post.joins(:access_levels).joins(:users).where (...) ActiveRecord为第二个连接(‘access_levels_users’)创建一个别名.我想在AccessLevel模型的“有效”范围内引用这个表名. V1显然生成一个PG :: AmbiguousColumn-Error. 这是我如何生成查询:(简体) # inside of a policy scope = Post. joins(:access_levels). where("access_levels.level" => 1,"access_levels.user_id" => current_user.id) # inside of my controller scope.joins(:users).select([ Post.arel_table[Arel.star],"hstore(array_agg(users.id::text),array_agg(users.email::text)) user_names" ]).distinct.group("posts.id") 生成的查询看起来像这样(使用上面的有效范围v2): SELECT "posts".*,hstore(array_agg(users.id::text),array_agg(users.email::text)) user_names FROM "posts" INNER JOIN "access_levels" ON "access_levels"."post_id" = "posts"."id" AND (("access_levels"."valid_from" IS NULL OR "access_levels"."valid_from" < '2014-07-24 05:38:09.274104') AND ("access_levels"."valid_until" IS NULL OR "access_levels"."valid_until" > '2014-07-24 05:38:09.274132')) INNER JOIN "users" ON "users"."id" = "access_levels"."user_id" INNER JOIN "access_levels" "access_levels_posts" ON "access_levels_posts"."post_id" = "posts"."id" AND (("access_levels"."valid_from" IS NULL OR "access_levels"."valid_from" < '2014-07-24 05:38:09.274675') AND ("access_levels"."valid_until" IS NULL OR "access_levels"."valid_until" > '2014-07-24 05:38:09.274688')) WHERE "posts"."deleted_at" IS NULL AND "access_levels"."level" = 4 AND "access_levels"."user_id" = 1 GROUP BY posts.id ActiveRecord为access_levels表的第二个连接设置一个合适的别名“access_levels_posts”. # v3 scope :valid,-> { where arel_table[:valid_from].eq(nil).or(arel_table[:valid_from].lt(Time.zone.now)).and( arel_table[:valid_until].eq(nil).or(arel_table[:valid_until].gt(Time.zone.now)) ) } 结果查询保持不变. 解决方法在更接近 similar question here这个问题后,我想出了一个更简单,更干净(对我的眼睛)解决这个问题的方案.我在这里粘贴另一个问题的答案的相关部分,以及您的范围.关键是找到一个方法来访问当前的isl_table对象,如果它们正在被使用,那么它的table_aliases在执行时就在该范围内.使用该表,您将能够知道是否在具有表名称别名(多个连接在同一个表上)的JOIN中使用范围,或者如果另一方面该范围没有表名称的别名. # based on your v2 scope :valid,-> { where("(#{current_table_from_scope}.valid_from IS NULL OR #{current_table_from_scope}.valid_from < :now) AND (#{current_table_from_scope}.valid_until IS NULL OR #{current_table_from_scope}.valid_until > :now)",:now => Time.zone.now) } def self.current_table_from_scope current_table = current_scope.arel.source.left case current_table when Arel::Table current_table.name when Arel::Nodes::TableAlias current_table.right else fail end end 我使用 如果你有兴趣,这里有一些参考我在路上使用: > A similar question on SO,用一大堆代码回答,你可以使用而不是你的美丽和简洁的能力. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |