2

I have three tables

  1. Company
  2. Code
  3. CompanyCode [join table] - to store company codes

Now, I want to find records for companies who have code 2,3 and 5 only.

I am trying with

Comapny.joins(:codes).where('codes.n_code' IN ? , [2,3,5])

but it will result all companies with only n_code = 2 or n_code = 3 or n_code = 5.

I want companies with n_code 2,3 and 5 with all these three values.

5
  • I am not familiar with RoR, but in SQL I believe you have to join codes table three times. Please, correct me if I am wrong. Commented Feb 24, 2016 at 10:18
  • @pumbo you are, you can do one join and specify the condition of the codes n_code being 2, 3 or 5. Commented Feb 24, 2016 at 10:26
  • @j-dexx give me an example in plain SQL, please Commented Feb 24, 2016 at 10:29
  • @pumbo I see what you meant now. I thought you meant active records .join because of rails associations rails is smart enough to automatically to perform the join on company codes and then codes for you. Commented Feb 24, 2016 at 10:30
  • you can use array_agg to gel a list of codes for every company and then filter for arrays that contain [2,3,5] Commented Feb 24, 2016 at 15:03

3 Answers 3

3

None of the previous answers is accurate. If you need to get records that have all specified values, but not only some of the values, you don't need to use WHERE n_code IN (2,3,5) condition, because it will get all records that have at least one of the values, but not all of them at the same time. Also, additional condition HAVING count(codes.n_code) = 3, as suggested earlier, is not a solution, as it does not guarantee that these 3 values are actually 2, 3 and 5.

I am not good at Ruby, so I will give you an example in plain SQL how you can get records that have all of the values:

SELECT company_codes.company_id
FROM company_codes
JOIN codes ON codes.id = company_codes.code_id
GROUP BY company_codes.company_id
HAVING array_agg(codes.n_code) @> ARRAY[2, 3, 5]

How it works: in HAVING section you aggregate all n_code values for a company into an array (note that the query is grouped by a company) and check that it contains the array on the right (contains all of its values).

Sign up to request clarification or add additional context in comments.

Comments

1

You could do something like this:

required_codes = [2, 3, 5]

Company.joins(:codes)
       .where(codes: { n_code: required_codes })
       .group('companies.id')
       .having('count(*) = ?', required_codes.count)

Maybe your group clause has to look a bit different depending on your table and field naming.

What it does is:

  • Get all companies that have codes
  • which contain one of the required codes
  • Group them, so that we have for example a group of 3 when the article has the codes 2, 3, 5, or just a group of 2 when the article has the tags 2, 3 and 6.
  • Then only take those groups with as many members as specified in our required codes array.

8 Comments

I want companies that have code [2,3,5] not only 2. Your answer will give me companies with code 2.
This should not be the case. Did you test the code and read the whole explanation?
.having('count(*) = ?', required_codes.count) - please explain these. I have read your explanation. but your code doesn't give me any result.
In your case it means that the group should have the same count as the required_codes array, which is 3.
Company.joins(:codes) .where(codes: { n_code: required_codes }) -> this result 56 companies . but after group by company id with code count = 3 . it results none. But company is available that have 3 codes.
|
0

Let do the query like this:

required_codes = [2, 3, 5]

sub_query = %Q{
  SELECT company_codes.company_id
  FROM company_codes
  JOIN codes
  ON codes.id = company_codes.code_id
  WHERE codes.n_code IN (#{required_codes.join(',')})
  GROUP BY company_codes.company_id
  HAVING COUNT(DISTINCT codes.n_code) = #{required_codes.size}
}

Company.where("id IN (#{sub_query})"

Explanation:

  • The sub_query just gets the company_id which has all required_codes and the distinct codes after grouping must equal the required_codes
  • After having company_id, we can easily query Company

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.