我拥有candidates
,candidate-skills
和skills
的MySql表。 这是最好的方式选择所有技能的候选人使用GROUP_CONCAT选择具备所有技能的候选人
我试过使用以下查询。但它不准确。
两点我想是:
- 所有的技能应显示(在评论中那里的条件时)
- 记录了所有的技能都被显示。 (具有一种技能的记录也显示为我正在使用阵列中的哪个位置)
我正在使用codeigniter框架。
http://sqlfiddle.com/#!9/b75c3/49
我拥有candidates
,candidate-skills
和skills
的MySql表。 这是最好的方式选择所有技能的候选人使用GROUP_CONCAT选择具备所有技能的候选人
我试过使用以下查询。但它不准确。
两点我想是:
我正在使用codeigniter框架。
http://sqlfiddle.com/#!9/b75c3/49
,而不是在那里使用having子句。
select `t`.*, GROUP_CONCAT(DISTINCT(s.name)) as skills,
GROUP_CONCAT(DISTINCT(s.id)) as skill_ids
FROM `candidates` `t`
LEFT JOIN `candidate-skills` `cs` ON `t`.`id` = `cs`.`can_id`
LEFT JOIN `skills` `s` ON `cs`.`skill_id` = `s`.`id`
GROUP BY `t`.`id`
having find_in_set ('8', skill_ids) and find_in_set ('10', skill_ids)
ORDER BY `t`.`id` desc
在笨
//take all skill ids in array
$ids=['8','10'];
$this->db->select("t.*");
$this->db->select("GROUP_CONCAT(DISTINCT(s.name)) as skills");
$this->db->select("GROUP_CONCAT(DISTINCT(s.id)) as skill_ids");
$this->db->from("candidates t");
$this->db->join("candidate-skills cs","t.id = cs.can_id");
$this->db->join("skills s","cs.skill_id = s.id");
$this->db->group_by("t.id");
foreach ($ids as $id) {
$this->db->having("find_in_set ('$id', skill_ids)");
}
$this->db->order_by("t.id","desc");
$query=$this->db->get();
$candidates=$query->result();
也许这
select t.* ,
s.skills,s.skills_id
FROM `candidates` `t`
join
(
select t.id tid, group_concat(s.name) skills, group_concat(s.id order by s.id) skills_id
FROM `candidates` `t`
LEFT JOIN `candidate-skills` `cs` ON `t`.`id` = `cs`.`can_id`
LEFT JOIN `skills` `s` ON `cs`.`skill_id` = `s`.`id`
group by t.id
) s
on s.tid = t.id
where instr(skills_id,'8,10') > 0
+----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+
| id | name | created_on | modified_on | is_deleted | skills | skills_id |
+----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+
| 1 | Eugine | 2017-05-23 11:44:30 | NULL | N | zend framework 2,bootstrap,wordpress | 8,10,12 |
| 2 | Frinoy Francis | 2017-05-23 16:44:29 | NULL | N | html,html5,zend framework 2,php,bootstrap | 1,4,8,10,11 |
+----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+
2 rows in set (0.03 sec)
MariaDB [sandbox]> select t.* ,
-> s.skills,s.skills_id
-> FROM `candidates` `t`
-> join
-> (
-> select t.id tid, group_concat(s.name) skills, group_concat(s.id order by s.id) skills_id
-> FROM `candidates` `t`
-> LEFT JOIN `candidate-skills` `cs` ON `t`.`id` = `cs`.`can_id`
-> LEFT JOIN `skills` `s` ON `cs`.`skill_id` = `s`.`id`
-> group by t.id
->) s
-> on s.tid = t.id
-> where instr(skills_id,'') > 0
-> ;
+----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+
| id | name | created_on | modified_on | is_deleted | skills | skills_id |
+----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+
| 1 | Eugine | 2017-05-23 11:44:30 | NULL | N | zend framework 2,bootstrap,wordpress | 8,10,12 |
| 2 | Frinoy Francis | 2017-05-23 16:44:29 | NULL | N | html,html5,zend framework 2,php,bootstrap | 1,4,8,10,11 |
| 3 | Arun | 2017-05-28 12:56:24 | NULL | N | bootstrap | 8 |
+----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+
3 rows in set (0.03 sec)
使用多个最灵活的方式的JOIN; GROUP_CONCAT和逗号分隔列表被认为是反模式,如果拼接没有按照正确的顺序完成(技能集1,2,5被认为与1,5,2不相同),它可能不起作用。
SELECT c.* FROM candidates AS c
JOIN candidateskills AS cs ON (cs.cand_id = c.id)
JOIN skills AS sk1 ON (cs.skill_id = sk1.id)
JOIN skills AS sk2 ON (cs.skill_id = sk2.id)
...other sk(N)...
WHERE (sk1.skill = 'waterskiing')
AND (sk2.skill = 'snowboarding')
...
;
这样的技能很容易剪裁,如果,例如,每个技能都有一个技能水平,你需要为滑雪要熟练达到或超过5级。这种灵活性是一个地狱做GROUP_CONCAT
。
但对于简单的匹配,则可以选择你想要的技能和快做只是对其计数:
SELECT c.* FROM candidates AS c
JOIN candidateskills AS cs ON (cs.cand_id = c.id)
WHERE cs.skill_id IN (1, 7, 24, 19, 115)
GROUP BY c.id
HAVING COUNT(1) = 5;
(在更合适的SQL你需要明确指出所有而不是C领域“c。*”,然后在GROUP BY子句中重复它们,只要你用c的主键进行分组,更聪明的RDBMS服务器就不会在意了。
对于每项技能,您都可以在技能上运行单个快速查询以检索其ID并组装上述查询。
或者你可以在一个单一的,大的查询,只要你有技巧的精确匹配做的:既然你想这在PHP
SELECT c.* FROM candidates AS c
JOIN candidateskills AS cs ON (cs.cand_id = c.id)
JOIN skills AS s ON (cs.skill_id = s.id)
WHERE s.skill IN ('javascript', 'html5', 'php')
GROUP BY c.id
HAVING COUNT(1) = 3;
:
$skills = array('javascript', 'html5', 'php');
$skno = count($skills);
$set = implode(',', array_fill('?', $skno));
$params = $skills;
$params[] = $skno;
$query = "SELECT c.* FROM candidates AS c
JOIN candidateskills AS cs ON (cs.cand_id = c.id)
JOIN skills AS s ON (cs.skill_id = s.id)
WHERE s.skill IN ({$set})
GROUP BY c.id
HAVING COUNT(1) = ?";
$stmt = $db->prepare($query);
$stmt->execute($params);
while ($candidate = $stmt->fetch(PDO::FETCH_ASSOC)) {
...
}
这是一个好解决方案,但仍然存在问题。技能ID可能是5,6,7,8,我们想要的可能是5和7.在这种情况下,这种解决方案将无法工作。 –
你可以拆分where条件,并加入一个和每个skill_id。 –