miguel.camba
miguel.camba

Reputation: 1827

Select records that have relations with all the given records

Quick summary.

An Offering has and belongs to many features A Feature has and belongs to many offerings

I want to find all Offerings that hace ALL the selected features.

Example:

When I call Offering.with_features([1,2,3]) I would expect to find ONLY the Offering_4 because is the only one that has the three features.

It might seem a silly question, but I can't find a good join that returns that result. All joins I've tested returs the offerings that have ANY of the given features, not ALL.

Ideas?

UPDATE

Following doublea's advice, I created tables with their own ID instead of join tables. It's solution is still valid, and I've implemented like this:

# offering.rb
def self.with_features(features)
  if features && features.any?
    where(id: FeatureOfferingRelation.with_all_features(features).pluck(:offering_id))
  else
    scoped
  end
end

# feature_offering_relation.rb
def self.with_all_features(features)
  select(:offering_id)
    .where(feature_id: features)
    .group(:offering_id)
    .having("count(distinct feature_id) = ?", features.size)
end

It works!! But I'll accept other ideas using joins instead of subqueries.

Upvotes: 0

Views: 130

Answers (1)

doublea
doublea

Reputation: 2576

Think the query will be something like this. Let me know if it works, else will test it out / fix it later.

"select offering_id from features_offerings where feature_id in (?) 
group by offering_id having count(distinct feature_id) = ?", 
feature_ids, feature_count

A couple things:

  1. Would recommend using a proper model as a join table, and thus has_many, :through, rather than has_and_belongs_to_many. Generally works out better for me. Think would make generating the query easier in this case.
  2. Would recommend tooling around with the Stanford DB class. The early videos on relational algebra and SQL queries were very helpful for me.

http://class2go.stanford.edu/db/Winter2013

Got to run. Again, reach out if you need more.

Cheers,

Upvotes: 1

Related Questions