MySQL多对多选择

时间:2017-03-28 18:52:26

标签: php mysql

我尝试创建MySQL多对多选择查询。我有三张桌子:

  • 配置文件
  • 技能
  • Profile_skills(个人资料ID和技能ID)

我希望能够搜索技能(例如PHP),并且所有具有该技能的配置文件都会显示在列表中,但包括所有其他技能。像大多数自由职业网站一样,我也可以看到他们知道MySQL等。

我还没有找到或想出正确方式来获取有关个人资料的所有信息,包括他们的所有技能。到目前为止,这是我最好的结果:

SELECT * FROM profiles INNER JOIN profile_skills ON 
profile_skills.profil_id = profiles.profil_id INNER JOIN skills ON
skills.skill_id = profile_skills.skill_id WHERE skill = 'PHP'

但是这只给了我一个技能而不是其他技能。

结果: http://imgur.com/E9PEiaU

预期: 拥有id,Skill" PHP"以及其他技能,例如" C#"如果用户ID 1拥有该技能。 http://imgur.com/5bCG4qo

因此,当我搜索具有技能的个人资料时,它还会显示其余的个人资料获取技能。

2 个答案:

答案 0 :(得分:0)

您可能希望子查询识别帐户,然后使用超级查询加载有关它们的详细信息(如果需要,还可以加载GROUP_CONCAT技能)。类似的东西:

SELECT profiles.*, GROUP_CONCAT(skills.skill SEPARATOR ', ') AS the_skillz
FROM profiles INNER JOIN profile_skills (...) INNER JOIN skills (...)
WHERE profiles.profile_id IN (
  SELECT DISTINCT profile_id 
  FROM profile_skills INNER JOIN skills (...) 
  WHERE skills.skill = 'PHP'
)
GROUP BY profiles.profile_id;

答案 1 :(得分:0)

您可以重新加入profile_skillsskills表格,以获得所需的结果。

SELECT p.*, s2.*
FROM skills s1
INNER JOIN profile_skills ps1 ON s.skill_id = ps1.skill_id
INNER JOIN profiles p ON ps1.profil_id = p.profil_id
INNER JOIN profile_skills ps2 ON p.profil_id = ps2.profil_id
INNER JOIN skills s2 ON ps2.skill_id = s2.skill_id
WHERE s1.skill = 'PHP'

这会得到这样的结果:

| p.id | p.name | s.id |       s.skill      |
---------------------------------------------
|  1   | rasmus |  1   |         PHP        |
|  1   | rasmus |  2   |        Linux       |
|  2   | thomas |  1   |         PHP        |
|  2   | thomas |  3   |  Eating Sandwiches |

有多种不同的方法可以将每个配置文件放在一行中并附上一系列技能。一种方法是在MySQL中使用GROUP_CONCAT

SELECT p.profil_id, p.profile_name, GROUP_CONCAT(s2.skill) AS skills
FROM skills s1
INNER JOIN profile_skills ps1 ON s.skill_id = ps1.skill_id
INNER JOIN profiles p ON ps1.profil_id = p.profil_id
INNER JOIN profile_skills ps2 ON p.profil_id = ps2.profil_id
INNER JOIN skills s2 ON ps2.skill_id = s2.skill_id
WHERE s1.skill = 'PHP'
GROUP BY p.profil_id

我添加了profile_name列,因为我不知道您的列实际是什么,您可以添加其他列,甚至仍然使用p.*。从技术上讲,profile中的其他列未定义为GROUP BY p.profil_id,您通常不应选择不包含在分组或某些聚合函数中的列,但MySQL会为你在这种情况下处理这个问题,因为它们对于具有相同p.profil_id的每一行都具有相同的值。

另一种方法是只使用第一个查询并在PHP中进行分组:

$previous_id = null;
while ($row = some_fetch_method()) {
    if ($row['profil_id'] != $previous_id) {
        echo "<h3>$row[profile_name]</h3>";
    }
    echo "<div>$row[skill]</div>";
}
显然,HTML并不是你所需要的,但它应该足以显示出一般的想法。