Reputation: 15
I would like to complicate this request by changing the scenario. Here is the link to the original request. Here is the link to the original request.
I have the following MySQL table called skills.
id | idUser | idSkill |
---|---|---|
1 | 4 | 1 |
2 | 8 | 4 |
3 | 8 | 9 |
4 | 13 | 9 |
5 | 18 | 2 |
6 | 22 | 1 |
7 | 27 | 2 |
8 | 32 | 4 |
9 | 11 | 2 |
10 | 32 | 9 |
10 | 32 | 7 |
I need to select, for example, all idUsers that have idSkill 4 and 9 at the same time (mandatory skills).
But I would like to have the possibility to search by optional idSkills (if any).
Mandatory skills are 9 and 4
Optional skill is 7
The result would be idUser 32.
I thought of this query:
SELECT id, idUser, idSkill FROM skills WHERE idSkill IN (9,4,7) GROUP BY idUser HAVING (idSkill IN (9,4))
But it clearly does not work.
Many thanks
Upvotes: 1
Views: 797
Reputation: 155
Your answer will be a simple query.
select * from (select distinct b.idUser, (select 1 from skill a where a.idUser=b.idUser and a.idSkill=4) 'four', (select 1 from skill a where a.idUser=b.idUser and a.idSkill=9) 'nine', (select 1 from skill a where a.idUser=b.idUser and a.idSkill=7) 'seven' from skill b) t where t.four=1 and t.nine=1 and t.seven=1
Upvotes: 0
Reputation: 164089
You can do it with aggregation and RANK()
window function.
This query:
SELECT idUser
FROM skills
WHERE idSkill IN (9, 4, 7)
GROUP BY idUser
HAVING SUM(idSkill IN (9, 4)) = 2 -- for the 2 mandatory skills
returns all the users with at least the 2 mandatory skills 9 and 4.
If you use an ORDER BY
clause with LIMIT
like this:
SELECT idUser
FROM skills
WHERE idSkill IN (9, 4, 7)
GROUP BY idUser
HAVING SUM(idSkill IN (9, 4)) = 2 -- for the 2 mandatory skills
ORDER BY COUNT(*) DESC
LIMIT 1
you will get from all the users with at least the 2 mandatory skills 9 and 4, only 1 user: the one with the largest number of skills (mandatory and optional).
If you want ties returned, use RANK()
window function:
SELECT idUser
FROM (
SELECT idUser, RANK() OVER (ORDER BY COUNT(*) DESC) rnk
FROM skills
WHERE idSkill IN (9, 4, 7)
GROUP BY idUser
HAVING SUM(idSkill IN (9, 4)) = 2 -- for the 2 mandatory skills
) t
WHERE rnk = 1
See the demo.
Upvotes: 1