Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I find the user that has both a cat and a dog?

I want to do a search across 2 tables that have a many-to-one relationship, eg

class User << ActiveRecord::Base
  has_many :pets
end

class Pet << ActiveRecord::Base
  belongs_to :users
end

Now let's say I have some data like so

users

id        name
1         Bob
2         Joe
3         Brian

pets

id        user_id  animal
1         1        cat
2         1        dog
3         2        cat
4         3        dog

What I want to do is create an active record query that will return a user that has both a cat and a dog (i.e. user 1 - Bob).

My attempt at this so far is

User.joins(:pets).where('pets.animal = ? AND pets.animal = ?','dog','cat')

Now I understand why this doesn't work - it's looking for a pet that is both a dog and a cat so returns nothing. I don't know how to modify this to give me the answer I want however. Does anyone have any suggestions? This seems like it should be easy - it doesn't seem like an especially unusual situation.

---edit---

Just adding a little coda to this question as I have just discovered Squeel. This allows you to build a subquery like so;

User.where{id.in(Pet.where{animal == 'Cat'}.select{user_id} & id.in(Pet.where{animal == 'Dog'}.select{user_id}))

This is what will find its way into my app.

like image 552
brad Avatar asked Jun 27 '11 06:06

brad


People also ask

Can a dog and cat co exist?

The majority of cats can happily coexist with a dog if they are given time to comfortably get to know each other. If a puppy and kitten are raised together, they generally will learn right away to tolerate each other, and some cats and dogs grow to be real friends, even playing and napping together.

How do you have both a cat and a dog?

"Before you start introductions, try scent swapping by providing each pet with an item that smells like the other. This gives them time to acclimate to each other's smell before meeting face-to-face, which can go a long way toward helping both animals adjust to having a new companion," she told Insider.

Can a dog birth a cat?

Cats and dogs cannot breed because they are two completely different species. Their chromosomes do not match; cats have 19 pairs of chromosomes while dogs have 39 pairs of chromosomes. This means it is impossible for them to breed.

Is there a cat dog hybrid?

Yesterday, Cornell University's School of Veterinary Medicine announced that it has produced the world's first proven live-born cat-dog hybrid in a joint venture with UC Davis and Massey University (New Zealand).


2 Answers

Andomar - Unfortunately, writing the query like that will not necessarily always work as desired. Specifically, having 2 cats will cause the user to show up, and having 3 pets - say, 2 cats and a dog - will cause them to be excluded.
I don't know much about ActiveRecord, but the following is standard SQL syntax that would work:

SELECT users.id
FROM Users
JOIN (SELECT user_id 
      FROM Pets
      WHERE animal IN ('dog', 'cat')
      GROUP BY user_id
      HAVING COUNT(DISTINCT animal)) Pets
  ON Pets.user_id = Users.id

This works differently than existing versions by counting the distinct "type" of pet ('cat' versus 'dog').

like image 61
Clockwork-Muse Avatar answered Sep 22 '22 18:09

Clockwork-Muse


Use sub-selects to constrain the results:

User.joins(:pets).where(
  'id IN (SELECT user_id FROM pets WHERE animal = ?) AND
   id IN (SELECT user_id FROM pets WHERE animal = ?)',
  'cat', 'dog')
like image 41
Jeremy Weathers Avatar answered Sep 21 '22 18:09

Jeremy Weathers