有什么方法可以替代左连接或者有必要吗?

时间:2015-06-11 10:51:53

标签: mysql sql left-join

我想知道是否有更好的方法来执行以下查询,或者是否有必要使其更好? (考虑到DB负载不是那么大)。唯一的标准是3个“变量”必须包含在AND中,并且查询可以有更多或更少的LEFT JOINS。

select `candidates`.* from `candidates` 
inner join `candidate_tag` on `candidates`.`id` = `candidate_tag`.`candidate_id` 
left join `tags` t1 on `t1`.`id` = `candidate_tag`.`tag_id` and t1.name like '%foo%'
left join `tags` t2 on `t2`.`id` = `candidate_tag`.`tag_id` and t2.name like '%baz%'
left join `tags` t3 on `t3`.`id` = `candidate_tag`.`tag_id` and t3.name like '%zoo%'
group by candidates.id
order by `candidates`.`last_name` asc

我的第一个镜头是使用AND运算符的条件查询,但它没有给我任何结果,所以我选择将其更改为left join s。

谢谢!

2 个答案:

答案 0 :(得分:4)

试试这个:

select `candidates`.id from `candidates` 
inner join `candidate_tag` on `candidates`.`id` = `candidate_tag`.`candidate_id` 
inner join `tags` t on `t`.`id` = `candidate_tag`.`tag_id`
group by candidates.id
HAVING SUM(CASE WHEN t.tag_name LIKE '%foo%' THEN 1 ELSE 0 END) >= 1 AND SUM(CASE WHEN t.tag_name LIKE '%bar%' THEN 1 ELSE 0 END) >= 1 AND SUM(CASE WHEN t.tag_name LIKE '%aaa%' THEN 1 ELSE 0 END) >= 1
order by `candidates`.`last_name` asc

答案 1 :(得分:1)

如果您想找到具有三个标签之一的候选人,您还可以使用条件聚合:

select c.*
from candidates c join
     candidate_tag ct
     on ct.candidate_id = c.id join
     tags t
     on ct.tag_id = t.id
where t.name like '%foo%' or
      t.name like '%baz%' or
      t.name like '%zoo%'
group by c.id
order by c.`last_name` asc;

您还可以添加group_concat(t.name) as tags以获取候选人匹配的代码。或者,如果您只想要所有三个候选人,您可以添加having子句:

having count(distinct t.name) = 3

having (max(t.name like '%foo%') +
        max(t.name like '%baz%') +
        max(t.name like '%zoo%')) = 3

如果有这个版本,你需要这个版本" foo"例如,标签。