使用成对值的查找行并找到确切的匹配组

发布于 2025-01-31 20:42:41 字数 2503 浏览 2 评论 0原文

我有这些表:

项目

ID名称版本
1pete0.0.1
2赃物0.0.1
3赃物0.0.2
4赃物0.0.3
5羽衣甘蓝0.0.1
6羽衣甘蓝0.0.2

id名称
1Jake
2Skye
3Kieth
4Jim
5 Eliz 5Eliz

Person_Project ID

Person_IdProject_id1
111
132
32 2 12
451
3 1 5 333 3
641
74 4 4 44
8 551
952
1055

人将拥有独特的项目,这意味着没有两个人会在同一项目上工作。

我正在编写一个基于Java的API,其中我收到一个带有不同项目的JSON请求,我必须退还正在从事请求确切项目的人。

请求:

[
    {"name": "Pete", "version": "0.0.1"}
]

这应该返回Jake

请求:

[
    {"name": "Pete", "version": "0.0.1"},
    {"name": "Swag", "version": "0.0.1"}
]

这应该返回Skye

请求:

[
    {"name": "Pete", "version": "0.0.1"},
    {"name": "Swag", "version": "0.0.2"}
]

这应该返回kieth

我正在为此编写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

这是不正确的,因为我在用于其他项目的版本中使用。

I have these tables:

Project

idnameversion
1Pete0.0.1
2Swag0.0.1
3Swag0.0.2
4Swag0.0.3
5Kale0.0.1
6Kale0.0.2

Person

idname
1Jake
2Skye
3Kieth
4Jim
5Eliz

Person_Project

idperson_idproject_id
111
221
322
431
533
641
744
851
952
1055

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不必在意 2025-02-07 20:42:41

您可以如此答案。您对说明确切的分区/无剩余部分感兴趣:

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)

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

雪花飘飘的天空 2025-02-07 20:42:41

这是一个经典关系划分无剩余的问题问题。

首先将输入数据放置在表变量或表值参数或temp中桌子。

然后,您可以使用标准关系划分答案之一

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)
);

这要做的就是以下内容:

  • 取以下行,以下存在子查询为真:
  • 对于每个person> person他们的所有person_project
  • 左 - 加入输入数据(同时加入匹配project)。
  • 对其进行分组并确保连接的匹配次数等于子查询中的行数...
  • ...数量也等于输入行的总数。

还有其他解决方案。

This is a classic Relational Division Without Remainder question.

Start by placing your input data into a table variable or a Table Valued Parameter or a temp table.

Then you can use one of the standard relational division answers

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)
);

db<>fiddle

What this does is the following:

  • Take all Person rows where the following EXISTS subquery is true:
  • For each Person take all their Person_Project rows
  • Left-join the input data (joining the matching Project at the same time).
  • Group it up and ensure that the number of matches from the join is equal to the number of rows in the subquery...
  • ... and the number is also equal to the total number of input rows.

There are other solutions to this also.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文