【问题标题】:Multiple joins with count and having with ActiveRecord多个连接计数和 ActiveRecord
【发布时间】:2018-08-27 23:03:06
【问题描述】:

我的申请是关于有很多愿望的个人资料,这些个人资料与电影相关:

class Profile < ApplicationRecord
  has_many :wishes, dependent: :destroy
  has_many :movies, through: :wishes
end

class Wish < ApplicationRecord
  belongs_to :profile
  belongs_to :movie
end

class Movie < ApplicationRecord
  has_many :wishes, dependent: :destroy
  has_many :profiles, through: :wishes
end

我想返回 ID 为 1、2 和 3 的个人资料所有“希望”的所有电影。

我设法使用原始 SQL (postgres) 获取此查询,但我想学习如何使用 ActiveRecord 进行此操作。

select movies.id
    from movies
    join wishes on wishes.movie_id = movies.id
    join profiles on wishes.profile_id = profiles.id and profiles.id in (1,2,3)
    group by movies.id
    having count(*) = 3;

(我依赖 count(*) = 3,因为我有一个唯一索引,可以防止创建具有重复 profile_id-movie_id 对的愿望,但我愿意接受更好的解决方案)

目前我发现最好的方法是这个:

profiles = Profile.find([1,2,3])
Wish.joins(:profile, :movie).where(profile: profiles).group(:movie_id).count.select { |_,v| v == 3 }

(我也会使用 Movie.joins 开始 AR 查询,但我没有找到方法 :-)

【问题讨论】:

    标签: ruby-on-rails activerecord rails-activerecord


    【解决方案1】:

    由于belongs_to 将外键放在wish 表中,您应该可以像这样查询它以获取您的个人资料:

    Wish.where("profile_id IN (?)", [1,2,3]).includes(:movie).all.map{|w| w.movie}
    

    这应该会为您提供这三个配置文件的所有电影数组,急切加载电影。

    【讨论】:

      【解决方案2】:

      由于我想要从查询中获取电影的集合,因此 ActiveRecord 查询需要从电影开始。我缺少的是我们可以在查询中指定表,例如where(profiles: {id: profiles_ids})

      这是我要查找的查询。 (是的,使用count 可能听起来有点脆弱,但替代方案是昂贵的 SQL 子查询。另外,我认为如果您使用多列唯一索引是安全的。)

      profiles_ids = [1,2,3]
      Movie.joins(:profiles).where(profiles: {id: profiles_ids}).group(:id).having("COUNT(*) = ?", profiles_ids.size)
      

      【讨论】:

        猜你喜欢
        • 2020-03-22
        • 1970-01-01
        • 2014-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-04
        • 1970-01-01
        • 2017-01-27
        相关资源
        最近更新 更多