【问题标题】:SQL join and many to many queriesSQL 连接和多对多查询
【发布时间】:2021-01-06 10:21:53
【问题描述】:

鉴于我有以下表格和记录,我有兴趣获取机构是美国国家航空航天局和欧洲航天局的所有任务。我写了一个内部连接语句,但我不知道如何将其缩小到我正在寻找的结果。仅供参考,我正在使用 sqlite

任务表

CREATE TABLE mission_agencies (
    id INTEGER NOT NULL, 
    name VARCHAR(250), 
    PRIMARY KEY (id)
)
id    name
1     m1
2     m2
3     m3
4     m4
5     m5

任务机构表

CREATE TABLE missions (
    _id INTEGER NOT NULL, 
    name VARCHAR(36) NOT NULL, 
    PRIMARY KEY (_id)
)
id    name
1     Nasa
2     Esa
3     Jax

任务所有权表(关联表)

CREATE TABLE mission_ownership (
    mission_id INTEGER, 
    mission_agency_id INTEGER, 
    FOREIGN KEY(mission_id) REFERENCES missions (id), 
    FOREIGN KEY(mission_agency_id) REFERENCES mission_agencies (id)
)
mission_id      mission_agency_id
1               1
2               1
3               1
4               2
1               2
5               3

我当前的 SQL 语句是这样的:

SELECT *
FROM missions
INNER JOIN mission_ownership
ON missions._id = mission_ownership.mission_id
INNER JOIN mission_agencies
ON mission_agencies._id = mission_ownership.mission_agency_id

这会产生一个像这样的表格:

id   name     mission_id    mission_agency_id     id    name
1    m1       1             1                     1     Nasa
2    m2       2             1                     1     Nasa
3    m3       3             1                     1     Nasa
4    m4       4             2                     2     Esa
1    m1       1             2                     2     Esa
5    m5       5             3                     3     Jax

现在我想运行一个查询,询问所有由 Nasa 和 Esa 完成的任务,满足此条件的唯一任务是 m1,所以我的目标结果集应该如下所示:

id   name     mission_id    mission_agency_id     id    name
1    m1       1             1                     1     Nasa
1    m1       1             2                     2     Esa

如何编写这样的查询?

【问题讨论】:

标签: mysql sql count inner-join window-functions


【解决方案1】:

如果您运行的是 MySQL 8.0,这里是一种使用窗口函数的方法:

select *
from (
    select *, count(*) over(partition by m.id) cnt
    from missions m
    inner join mo on m.id = mo.mission_id
    inner join ma on ma.id = mo.mission_agency_id
    where ma.name in ('Nasa', 'Esa')
) t
where cnt > 1

我们的想法是根据您感兴趣的机构过滤您当前的结果集,并计算每个任务剩余的行数。然后,我们可以过滤同时拥有这两个机构的任务。

请注意,这假定没有重复的任务/机构。

【讨论】:

  • 谢谢,我按照你的建议解决了。
【解决方案2】:

按照此处建议的过滤和计数行的想法,我发现了一个像这样工作的查询:

SELECT COUNT(mid), mname
FROM(
    SELECT missions._id AS mid, missions.name AS mname
    FROM missions
    INNER JOIN mission_ownership
    ON missions._id = mission_ownership.mission_id
    INNER JOIN mission_agencies
    ON mission_agencies._id = mission_ownership.mission_agency_id
    WHERE mission_agencies.name = 'Esa' or mission_agencies.name = 'Jax'
    )
GROUP BY mid
HAVING COUNT(mid) > 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 2023-04-08
    • 1970-01-01
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多