I have these tables:
Project
id name version
---------------------
1 Pete 0.0.1
2 Swag 0.0.1
3 Swag 0.0.2
4 Swag 0.0.3
5 Kale 0.0.1
6 Kale 0.0.2
Person
id name
----------
1 Jake
2 Skye
3 Kieth
4 Jim
5 Eliz
Person_Project
id person_id project_id
-------------------------
1 1 1
2 2 1
3 2 2
4 3 1
5 3 3
6 4 1
7 4 4
8 5 1
9 5 2
10 5 5
Persons will have unique projects, means no two persons will work on the same projects.
I am writing a java based api where I receive a json request with different projects and I have to return the person who is working on exact projects given in request.
Request:
[
{
"name":"Pete",
"version":"0.0.1"
}
]
This should return Jake
Request:
[
{
"name": "Pete",
"version": "0.0.1"
},
{
"name": "Swag",
"version": "0.0.1"
}
]
This should return Skye
Request:
[
{
"name": "Pete",
"version": "0.0.1"
},
{
"name": "Swag",
"version": "0.0.2"
}
]
This should return Kieth
I am writing SQL for this and not getting what I needed.
This is what I am up to
SELECT pe.id, pe.name
FROM person pe
LEFT JOIN person_project pepr on pepr.person_id = pe.id
WHERE pe.id in (SELECT pepr.person_id
FROM project pr
LEFT JOIN person_project pepr ON pepr.project_id = pr.id
WHERE pr.name IN ('Pete', 'Swag')
AND pr.version IN ('0.0.1', '0.0.2')
GROUP BY pepr.project_id
HAVING COUNT(pepr.project_id) = 2)
GROUP BY pe.id, pe.name
HAVING COUNT(pe.id) = 2
This is not right as I am using IN for versions which will gets applied to other projects.
CodePudding user response:
You can use SQL relational division logic as described in this answer. You're interested in the part that says exact division/no remainder:
with project_list as (
select id
from project
where exists (
select *
from (values
('pete', '0.0.1'),
('swag', '0.0.1')
) as user_input(name, version)
where project.name = user_input.name and project.version = user_input.version
)
), person_project_copy as (
select person_id, case when project_list.id is not null then 1 end as is_required
from person_project
left join project_list on person_project.project_id = project_list.id
)
select person_id
from person_project_copy
group by person_id
having count(is_required) = (select count(*) from project_list)
and count(*) = (select count(*) from project_list)