13

I have a Client model and a Product model where a Client has many Products and a Product belongs to a CLient.

I need to find a query that only returns Clients if they have a record in the Product table

clients table

id |      name
--------------
 1 | Company A
 2 | Company B
 3 | Company C

products table

id |      name |  client_id
---------------------------
 1 | Product A |         1
 2 | Product B |         1
 3 | Product C |         3
 4 | Product D |         3
 5 | Product E |         1

I only need Clients 1 3

For example something like

@clients = Client.where("client exists in products")  #something to this effect
4

4 に答える 4

23

Simplest but not the fastest:

Client.where(:id => Product.select(:client_id).map(&:client_id))

SQL subquery (more faster):

Client.where("EXISTS(SELECT 1 from products where clients.id = products.client_id)")
于 2013-01-07T06:13:55.007 に答える
7

Here's another solution. It's a subquery like Valery's second solution, but without writing out the sql:

Client.where(Product.where(client_id: Client.arel_table[:id]).exists)
于 2015-07-28T18:34:20.063 に答える
6

Here is the solution which uses Where Exists gem (disclosure: I'm its author):

Client.where_exists(:products)
于 2015-08-30T18:53:59.120 に答える
1

Another gem that exists to do that: activerecord_where_assoc (I'm the author)

With it:

Client.where_assoc_exists(:products)

If you had to also specify some of the products, when you could do it like this:

Client.where_assoc_exists(:products, id: my_products.map(&:id))

Doing it without a gem makes it easy to do mistakes.

Read more in the documentation. Here is an introduction and examples.

于 2020-02-09T17:29:53.713 に答える