SeaSky
SeaSky

Reputation: 1314

Preventing multi-row returns while using INNER JOIN and IN clause: MySQL

I have multiple tables that I am joining together to return a search result page. In the search page, the user can toggle criteria and the page dynamically reloads the results based on query results. I am having a challenge with one particular condition in this regard -

I have a table called jobs and another table called job_contract. A job can have one or more contract types associated with it - the simple query to join these two together is

SELECT a.job_id, c.contract_type_name FROM job a
INNER JOIN job_contract c ON a.job_id = c.job_id

This query works fine. However if the user decides to toggle some contract types and selects multiple contract types then the query returns multiple rows with the same job id. The query I am using is as below

SELECT a.job_id, c.contract_type_name FROM job a
INNER JOIN job_contract c ON a.job_id = c.job_id AND c.contract_type IN (1,2,4)

So for the above code, if a job does have multiple contract type association then I get 3 rows. Can I limit this to 1 row without using a DISTINCT clause - I am concerned about performance problems by using DISTINCT

Thank you very much for your help in advance

Upvotes: 0

Views: 83

Answers (2)

Gordon Linoff
Gordon Linoff

Reputation: 1269733

If you don't need the contract name, you can do this with an exists clause:

select j.job_id
from job j
where exists (select 1
              from job_contract jc
              where j.job_id = jc.jobid and jc.contract_type IN (1,2,4)
             );

This eliminates the group by/distinct. It will perform best with an index on job_contract(job_id, contract_type).

You can then get the contracts using:

select j.job_id,
       (select group_concat(contract_type_name)
        from job_contract jc
        where j.job_id = jc.jobid and jc.contract_type IN (1,2,4)
       ) as contracts
from job j
where exists (select 1
              from job_contract jc
              where j.job_id = jc.jobid and jc.contract_type IN (1,2,4)
             );

I would recommend that you use group by/distinct because of the clarity of the query, unless you have a good reason not to.

Upvotes: 1

jessepinho
jessepinho

Reputation: 5772

Add GROUP BY a.job_id. This will group together the results for each job ID into one row.

If you'd still like to see all the contract_type_names for a single job, you could use a concatenation function like GROUP_CONCAT().

EDIT: Just to be clear, here's what your full query could look like:

SELECT
  a.job_id,
  GROUP_CONCAT(c.contract_type_name SEPARATOR ', ')
FROM
  job a
  INNER JOIN job_contract c
    ON a.job_id = c.job_id
WHERE
  c.contract_type IN (1,2,4)
GROUP BY a.job_id

Upvotes: 0

Related Questions