使用值对查找行并找到完全匹配的组
Lookup rows using pairs of values and find exact matching groups
我有这些表:
项目
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
人
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
每个人都有独特的项目,这意味着没有两个人会在同一个项目上工作。
我正在写一个基于 java 的 api,我收到了一个 json 不同项目的请求,我必须 return 正在从事确切项目的人在请求中给出。
要求:
[
{"name": "Pete", "version": "0.0.1"}
]
这应该returnJake
要求:
[
{"name": "Pete", "version": "0.0.1"},
{"name": "Swag", "version": "0.0.1"}
]
这应该returnSkye
要求:
[
{"name": "Pete", "version": "0.0.1"},
{"name": "Swag", "version": "0.0.2"}
]
这应该returnKieth
我正在为此写 SQL,但没有得到我需要的东西。
这就是我要做的
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
这是不对的,因为我将 IN 用于将应用于其他项目的版本。
您可以使用 SQL 关系除法逻辑,如 this answer 中所述。您对精确 division/no 余数部分感兴趣:
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)
这是一道经典的Relational Division Without Remainder题。
首先将您的输入数据放入 table 变量或 Table 值参数或临时 table.
那么你可以使用标准关系除法答案之一
SELECT
p.name
FROM Person p
WHERE EXISTS (SELECT 1
FROM Person_Project pp
LEFT JOIN @input i
JOIN Project prj ON prj.name = i.name AND prj.version = i.version
ON pp.project_id = prj.id
WHERE pp.person_id = p.id
HAVING COUNT(prj.id) = COUNT(*)
AND COUNT(prj.id) = (SELECT COUNT(*) FROM @input)
);
它的作用如下:
- 获取满足以下
EXISTS
子查询的所有 Person
行:
- 对于每个
Person
取其所有 Person_Project
行
- Left-join输入数据(同时加入匹配
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 |
人
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 |
每个人都有独特的项目,这意味着没有两个人会在同一个项目上工作。
我正在写一个基于 java 的 api,我收到了一个 json 不同项目的请求,我必须 return 正在从事确切项目的人在请求中给出。
要求:
[
{"name": "Pete", "version": "0.0.1"}
]
这应该returnJake
要求:
[
{"name": "Pete", "version": "0.0.1"},
{"name": "Swag", "version": "0.0.1"}
]
这应该returnSkye
要求:
[
{"name": "Pete", "version": "0.0.1"},
{"name": "Swag", "version": "0.0.2"}
]
这应该returnKieth
我正在为此写 SQL,但没有得到我需要的东西。
这就是我要做的
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
这是不对的,因为我将 IN 用于将应用于其他项目的版本。
您可以使用 SQL 关系除法逻辑,如 this answer 中所述。您对精确 division/no 余数部分感兴趣:
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)
这是一道经典的Relational Division Without Remainder题。
首先将您的输入数据放入 table 变量或 Table 值参数或临时 table.
那么你可以使用标准关系除法答案之一
SELECT
p.name
FROM Person p
WHERE EXISTS (SELECT 1
FROM Person_Project pp
LEFT JOIN @input i
JOIN Project prj ON prj.name = i.name AND prj.version = i.version
ON pp.project_id = prj.id
WHERE pp.person_id = p.id
HAVING COUNT(prj.id) = COUNT(*)
AND COUNT(prj.id) = (SELECT COUNT(*) FROM @input)
);
它的作用如下:
- 获取满足以下
EXISTS
子查询的所有Person
行: - 对于每个
Person
取其所有Person_Project
行 - Left-join输入数据(同时加入匹配
Project
)。 - 将其分组并确保来自连接的匹配项数等于子查询中的行数...
- ... 并且数字也等于输入行的总数。
还有其他解决方案。