SQL中与其他表的所有记录相关的记录

发布于 2024-09-10 13:07:48 字数 177 浏览 4 评论 0原文

假设关系数据库中有三个表:

Person {id, name}
Obstacle {id, name}
Person_overcomes_obstacle {person_id, obstacle_id}

我想编写一个查询来告诉我是否至少有一个人克服了所有障碍。有想法吗?

Let's say we have three tables in a relational database:

Person {id, name}
Obstacle {id, name}
Person_overcomes_obstacle {person_id, obstacle_id}

I want to write a query that tells me if at least one person has overcome all obstacles. Ideas?

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

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

发布评论

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

评论(4

淡看悲欢离合 2024-09-17 13:07:48

我注意到我是唯一使用 Person_overcomes_obstacle 自然表别名的人!

您需要一个 关系划分对此进行查询。

您可以计算 Person_overcomes_obstacle 中的障碍和匹配记录,并返回两个数字匹配的记录,或者以另一种方式看待它,即查找没有未克服的障碍的人。

SELECT p.id, p.name /*Or use COUNT(*) or wrap in Exists 
                     if you don't care about ids and names*/
FROM Person p
WHERE NOT EXISTS
   (SELECT * FROM Obstacle o
    WHERE NOT EXISTS 
    (
       SELECT * FROM Person_overcomes_obstacle poo
       WHERE poo.person_id = p.id and o.id = poo.obstacle_id
    )
)

I notice that I was the only person to use the natural table alias for Person_overcomes_obstacle!

You need a relational division query for this.

You can either count up the obstacles and the matching records in Person_overcomes_obstacle and return ones where the 2 numbers match or look at it another way as finding people for which there is no obstacle that they haven't overcome.

SELECT p.id, p.name /*Or use COUNT(*) or wrap in Exists 
                     if you don't care about ids and names*/
FROM Person p
WHERE NOT EXISTS
   (SELECT * FROM Obstacle o
    WHERE NOT EXISTS 
    (
       SELECT * FROM Person_overcomes_obstacle poo
       WHERE poo.person_id = p.id and o.id = poo.obstacle_id
    )
)
玩物 2024-09-17 13:07:48
SELECT 
    p.name,
    COUNT(DISTINCT oo.obstacle_id) AS OBSTACLES_COMPLETED
FROM 
    person p

    JOIN person_overcomes_obstacle oo
    ON oo.person_id = p.person_id

GROUP BY 
    p.name

HAVING 
    COUNT(DISTINCT poo.obstacle_id) = (SELECT COUNT(id) FROM obstacle)
SELECT 
    p.name,
    COUNT(DISTINCT oo.obstacle_id) AS OBSTACLES_COMPLETED
FROM 
    person p

    JOIN person_overcomes_obstacle oo
    ON oo.person_id = p.person_id

GROUP BY 
    p.name

HAVING 
    COUNT(DISTINCT poo.obstacle_id) = (SELECT COUNT(id) FROM obstacle)
巨坚强 2024-09-17 13:07:48

用途:

SELECT poo.person_id
    FROM PERSON_OVERCOMES_OBSTACLE poo
GROUP BY poo.person_id
    HAVING COUNT(DISTINCT poo.obstacle_id) = (SELECT COUNT(*) 
                                                                        FROM OBSTACLE)

这是一种不太可能表现良好的替代方案:

SELECT x.person_id
   FROM (SELECT poo.person_id,
                         COUNT(DISTINCT poo.obstacle_id) AS obs_overcome,
                         (SELECT COUNT(*) 
                             FROM OBSTACLE) AS obs_total
                 FROM PERSON_OVERCOMES_OBSTALCE poo
          GROUP BY poo.person_id) x
 WHERE x.obs_overcome = x.obs_total

无论哪种情况,您都可以加入 PERSON 表以获取更多信息(如果您愿意) - 或者您可以从以下任一位置对 person_id 进行计数查询以了解有多少人完成了记录的所有障碍。

Use:

SELECT poo.person_id
    FROM PERSON_OVERCOMES_OBSTACLE poo
GROUP BY poo.person_id
    HAVING COUNT(DISTINCT poo.obstacle_id) = (SELECT COUNT(*) 
                                                                        FROM OBSTACLE)

This is an alternative that is less likely to perform well:

SELECT x.person_id
   FROM (SELECT poo.person_id,
                         COUNT(DISTINCT poo.obstacle_id) AS obs_overcome,
                         (SELECT COUNT(*) 
                             FROM OBSTACLE) AS obs_total
                 FROM PERSON_OVERCOMES_OBSTALCE poo
          GROUP BY poo.person_id) x
 WHERE x.obs_overcome = x.obs_total

In either case, you can join to the PERSON table to get more information if you want - or you could run a count on person_id from either query to know how many people completed all the obstacles recorded.

趁微风不噪 2024-09-17 13:07:48

这个 SELECT 应该返回没有人克服的障碍的数量。如果计数为零,则至少有一个人克服了所有障碍。

SELECT count(*)
  FROM (SELECT po.person_id, o.obstacle_id
          FROM Obstacle o
          LEFT OUTER JOIN Person_overcomes_obstacle po
            ON (o.obstacle_id = po.obstacle_id)) t
WHERE t.person_id IS NULL

您也可以这样做,以获得相同的效果(并且可能有更好的性能):

SELECT count(*)
  FROM Obstacle o
 WHERE NOT EXISTS (SELECT 1
                     FROM Person_overcomes_obstacle po
                    WHERE po.obstacle_id = o.obstacle_id)

编辑:正如评论中指出的,上述两个查询仅证明没有任何人克服的障碍,而不是单个人克服的所有障碍。

除此之外,仍然可以证明单个用户已经克服了所有障碍,而无需查询 Person 表:

SELECT t.personid, count(*)
  FROM (SELECT DISTINCT po.person_id, o.obstacle_id
          FROM Obstacle o
          JOIN Person_overcomes_obstacle po
            ON (o.obstacle_id = po.obstacle_id)) t
 GROUP BY t.persion_id
 HAVING count(*) = (SELECT count(*)
                      FROM obstacle)

This SELECT should return the number of obstacles that nobody has overcome. If the count is zero then all the obstacles have been overcome by at least one person.

SELECT count(*)
  FROM (SELECT po.person_id, o.obstacle_id
          FROM Obstacle o
          LEFT OUTER JOIN Person_overcomes_obstacle po
            ON (o.obstacle_id = po.obstacle_id)) t
WHERE t.person_id IS NULL

You could also do this, for the same effect (and possibly better performance):

SELECT count(*)
  FROM Obstacle o
 WHERE NOT EXISTS (SELECT 1
                     FROM Person_overcomes_obstacle po
                    WHERE po.obstacle_id = o.obstacle_id)

EDIT: As pointed out in the comments, the above two queries only prove that there are no obstacles that nobody has overcome, and not that a single individual has overcome all obstacles.

That aside, it should still be possible to prove that a single user has overcome all obstacles without querying the Person table:

SELECT t.personid, count(*)
  FROM (SELECT DISTINCT po.person_id, o.obstacle_id
          FROM Obstacle o
          JOIN Person_overcomes_obstacle po
            ON (o.obstacle_id = po.obstacle_id)) t
 GROUP BY t.persion_id
 HAVING count(*) = (SELECT count(*)
                      FROM obstacle)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文