Domanda

Sono cavarsela mia strada attraverso di gran lunga la query SQL più complesse che abbia mai fatto, che è probabilmente estremamente semplice per la maggior parte di voi (:

Ho tre tabelle, per l'utente, le competenze e l'User_Skills. I campi di cui dovrebbero essere abbastanza autoesplicativo.

Voglio scegliere le persone che hanno una o più abilità che soddisfano i miei criteri.

Posso selezionare un utente con l'abilità che sto cercando, ma non sono sicuro sulla sintassi per l'interrogazione molteplici competenze.

mi piacerebbe usare solo una query, quindi sto cercando di usare group_concat

Ecco il mio 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

Come faccio a limitare la ricerca a solo le persone che hanno abilità 5 e 9?

È stato utile?

Soluzione

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
        )

Questo si basa sul fatto che è un (user_id, skill_id) PRIMARY KEY o un tasto UNIQUE (cioè non è possibile assegnare una competenza a un utente più di una volta).

Aggiornamento:

Per tornare tutte le abilità (separati da virgola):

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
        )

Altri suggerimenti

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

Se si vuole evitare che più record di abilità, allora potrebbe essere necessario un subquery

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

Perché non puoi semplicemente utilizzare un INNER JOIN inplace della LEFT JOIN, ed emettere una clausola WHERE per le competenze necessarie?

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

Ecco come (vi darà agli utenti con competenze 5 e 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

Hai solo bisogno di un

HAVING FIND_IN_SET('5', skills) AND FIND_IN_SET('9', skills)

dopo che il gruppo da (in cui "competenze" è il nome della colonna raggruppate). Quindi la query dovrebbe apparire come

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)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top