[英]How to JOIN three tables with IN array filter, but still get all the rows from third table
我有通过UserSkills表连接的Users and Skills表,用于多对多关系。 这是表格中的内容:
Users (id, username)
Skills (id, name)
UserSkills (user_id, skill_id)
我在寻找['C#','SQL']的各种技能。 因此,我正在进行IN过滤操作的加入,以仅获取我需要的那些用户。
SELECT (username, GROUP_CONCAT(Skills.name)) FROM Users
JOIN UserSkills ON Users.id = UserSkills.user_id
JOIN Skills ON Skills.id = UserSkills.skill_id AND Skills.name IN ('C#', 'SQL')
GROUP BY Users.id
我想获得相同的用户列表,但要拥有所有技能,不仅是我要寻找的用户。 例如:
In my case I get: username: 'joe' | skills: 'C#', 'SQL'
I want to get: username: 'joe' | skills : 'C#', 'SQL', 'JavaScript', 'NodeJS'
请帮忙。
最直接的方法是第二次加入:
SELECT u.username, GROUP_CONCAT(DISTINCT userS.name)
FROM Users AS u
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS filterS ON filterS.id = us.skill_id AND filterS.name IN ('C#', 'SQL')
INNER JOIN Skills AS userS ON userS.id = us.skill_id
GROUP BY u.id
但是您将需要GROUP_CONCAT中的DISTINCT,因为过滤器技能将基本上与用户技能交叉连接。 同样值得注意的是,该查询使用户具备了并非全部指定的任何技能。 这是一个更好的解决方案:
SELECT u.username, GROUP_CONCAT(s.name) AS skils
, COUNT(CASE WHEN s.name IN ('C#', 'SQL') THEN 1 ELSE NULL END) AS matchedSkillCount
FROM Users AS u
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS s ON s.id = us.skill_id
GROUP BY u.id
HAVING matchedSkillCount > 0 -- You can replace 0 with the number of matches you want
;
...但是在非常大的数据库中,以上内容可能会变得昂贵; 其他几个选择:
SELECT u.username, GROUP_CONCAT(DISTINCT userS.name)
FROM Skills AS filterS
INNER JOIN UserSkills AS ufs ON filterS.id = ufs.skill_id
INNER JOIN Users AS u ON ufs.user_id = u.id
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS userS ON us.skill_id = userS.id
WHERE filterS.name IN ('C#', 'SQL')
GROUP BY u.id;
SELECT u.username, GROUP_CONCAT(s.name) AS skils
FROM Users AS u
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS sON s.id = us.skill_id
WHERE u.id IN (
SELECT DISTINCT ufs.user_id
FROM Skills AS filterS
INNER JOIN UserSkills AS ufs ON filterS.id = ufs.skill_id
WHERE filterS.name IN ('C#', 'SQL')
)
GROUP BY u.id
;
从逻辑上讲,WHERE在连接后应用; 但是大多数RDBMS(如MySQL)都通过使用WHERE条件来优化执行,以最大程度地减少连接在一起的行。
select USERS.name,GROUP_CONCAT(Skills.name) from USERS join USERSKILLS on users.id =
USERSKILLS.user_id join skills on USERSKILLS.SKILL_ID = skills.ID and users.id in (
select distinct users.id from
users join USERSKILLS on users.id = USERSKILLS.user_id join skills on skills.id = userSkills.skill_id and
Skills.name IN ('C#', 'SQL'))
group by USERS.name;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.