简体   繁体   English

使用INNER JOIN和IN子句时防止多行返回:MySQL

[英]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. 我有一个名为Jobs的表和另一个名为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. 但是,如果用户决定切换某些合同类型并选择多种合同类型,则查询将返回具有相同作业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. 因此,对于上面的代码,如果一项工作确实具有多个合同类型关联,那么我将获得3行。 Can I limit this to 1 row without using a DISTINCT clause - I am concerned about performance problems by using DISTINCT 我可以不使用DISTINCT子句将其限制为1行吗?-我担心使用DISTINCT会导致性能问题

Thank you very much for your help in advance 非常感谢您的提前帮助

If you don't need the contract name, you can do this with an exists clause: 如果不需要合同名称,则可以使用exists子句来实现:

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 . 这消除了group by / distinctgroup by It will perform best with an index on job_contract(job_id, contract_type) . 结合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. 由于查询的明确性,我建议您使用group by / distinct ,除非您有充分的理由不这样做。

Add GROUP BY a.job_id . 添加GROUP BY a.job_id This will group together the results for each job ID into one row. 这会将每个作业ID的结果分组在一起。

If you'd still like to see all the contract_type_name s for a single job, you could use a concatenation function like GROUP_CONCAT() . 如果您仍想查看单个作业的所有contract_type_name ,则可以使用诸如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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM