MYSQL sélectionner les utilisateurs ayant des compétences spécifiques
-
20-09-2019 - |
Question
J'embrouillant mon chemin à travers de loin la requête SQL les plus complexes que j'ai jamais fait, ce qui est probablement extrêmement simple pour la plupart d'entre vous (:
J'ai trois tableaux, l'utilisateur, des compétences et User_Skills. Les champs dont devrait être assez explicite.
Je veux choisir les personnes qui ont une ou plusieurs compétences qui répondent à mes critères.
Je peux sélectionner un utilisateur avec la compétence que je suis après, mais je ne suis pas sûr de la syntaxe pour effectuer des requêtes multiples compétences.
Je voudrais simplement utiliser une requête, donc je suis en train d'utiliser GROUP_CONCAT
Voici mon SQL:
SELECT User_id, first_name, last_name, county, GROUP_CONCAT(CAST(Skill_id AS CHAR))
FROM User LEFT JOIN User_Skills ON User.id = User_Skills.User_id
LEFT JOIN Skills ON User_Skills.Skill_id = Skills.id GROUP BY User_id
User_id first_name last_name county GROUP_CONCAT(CAST(Skill_id AS CHAR))
1000 Joe Blow West Yorkshire 8,6,1,9,7,3,5,10
1001 Fred Bloggs COUNTY1 5,8,2,7,9
1003 asdf asdf1 Some County 10,8,2
Comment puis-je limiter la recherche aux seules personnes qui ont des compétences 5 et 9?
La solution
SELECT *
FROM users u
WHERE EXISTS
(
SELECT NULL
FROM user_skills us
WHERE us.skill_id IN (5, 9)
AND us.user_id = u.id
LIMIT 1, 1
)
Cela repose sur le fait que (user_id, skill_id)
est un PRIMARY KEY
ou une clé UNIQUE
(qui vous ne pouvez pas attribuer une compétence à un utilisateur plus d'une fois).
Mise à jour:
Pour revenir toutes les compétences (séparées par des virgules):
SELECT u.*,
(
SELECT GROUP_CONCAT(skill_id)
FROM user_skills uso
WHERE uso.user_ud = u.user_id
) AS all_skills
FROM users u
WHERE EXISTS
(
SELECT NULL
FROM user_skills us
WHERE us.skill_id IN (5, 9)
AND us.user_id = u.id
LIMIT 1, 1
)
Autres conseils
SELECT User_id, first_name, last_name, county, GROUP_CONCAT(CAST(Skill_id AS CHAR))
FROM User JOIN User_Skills ON User.id = User_Skills.User_id
JOIN Skills ON User_Skills.Skill_id IN (5,9)
GROUP BY User_id
Si vous voulez éviter plusieurs enregistrements de compétences, alors vous devrez peut-être un sous-requête
SELECT User_id, first_name, last_name, county,
(
SELECT (GROUP_CONCAT(CAST(subSkill.Skill_id AS CHAR))
FROM Skills as subSkill WHERE subSkill.skill_id = User_Skills.skill_id
GROUP BY subSkill.skill_id
)
FROM User JOIN User_Skills ON User.id = User_Skills.User_id
JOIN Skills ON User_Skills.Skill_id IN (5,9)
GROUP BY User_id
Pourquoi ne pouvez-vous utiliser juste un INNER JOIN enplace de la jointure gauche, et émettre une clause WHERE pour les compétences requises?
SELECT User_id, first_name, last_name, county, GROUP_CONCAT(CAST(Skill_id AS CHAR))
FROM User
INNER JOIN User_Skills ON User.id = User_Skills.User_id
INNER JOIN Skills ON User_Skills.Skill_id = Skills.id GROUP BY User_id
WHERE skill_id = 5 OR skill_id=9
Voilà comment (vous donnera aux utilisateurs des compétences 5 et 9):
SELECT User_id, first_name, last_name, county FROM User INNER JOIN User_Skills ON User.id = User_Skills.User_id INNER JOIN Skills ON User_Skills.Skill_id = Skills.id WHERE Skills.Skill_id = 5 AND Skills.Skill_id = 9 GROUP BY User_id
Vous avez juste besoin d'un
HAVING FIND_IN_SET('5', skills) AND FIND_IN_SET('9', skills)
après que le groupe par (où « compétences » est le nom de la colonne groupée). Donc, votre requête devrait ressembler à
SELECT User_id, first_name, last_name, county, GROUP_CONCAT(CAST(Skill_id AS CHAR)) as skills
FROM User LEFT JOIN User_Skills ON User.id = User_Skills.User_id
LEFT JOIN Skills ON User_Skills.Skill_id = Skills.id GROUP BY User_id
HAVING FIND_IN_SET('5', skills) AND FIND_IN_SET('9', skills)