簡體   English   中英

如何使用IN數組過濾器聯接三個表,但仍從第三個表獲取所有行

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM