Home > Enterprise >  SQL: query and condition on two columns with a list
SQL: query and condition on two columns with a list

Time:05-25

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)

DB<>Fiddle for all three examples

  • Related