user3413468
user3413468

Reputation: 257

Best way to combine results of two select statements without returning an array?

I'm trying to get one set of unique users from querying two different tables. For example, let's say I want to find the set of unique pet owners. Some owners own dogs, some own cats- I want the number of owners who own a dog or a cat or both.

I know one solution is

dog_owners = Dog.joins(:owner).select(:owner_id).distinct
cat_owners = Cat.joins(:owner).select(:owner_id).distinct
combined_owners = dog_owners + cat_owners
unique_owners = combined_owners.uniq{|x| x.owner_id}
unique_owners.count 

Is there a way to do this where I wouldn't have to use the uniq call, and could use distinct instead? Because the + operator returns an Array, I am not able to use distinct here.

Upvotes: 0

Views: 122

Answers (2)

gabrielhilal
gabrielhilal

Reputation: 10769

Can you go the other way around?

Owner
   .left_outer_joins(:dogs, :cats)
   .where("dogs.owner_id IS NOT NULL OR cats.owner_id IS NOT NULL")
   .distinct

Upvotes: 2

Jay-Ar Polidario
Jay-Ar Polidario

Reputation: 6603

I think gabrielhilal's answer is better. I'm just putting it here for anyone who would probably have same requirements as OP but with needed flexibility in the conditions.

owners = Owner.where(
  id: Dog.joins(:owner).select(:owner_id)
).or(
  Owner.where(
    id: Cat.joins(:owner).select(:owner_id)
  )
)

Upvotes: 0

Related Questions