1

リレーショナルデータベースに3つのテーブルがあるとしましょう。

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

少なくとも1人の人がすべての障害を克服したかどうかを教えてくれるクエリを書きたいと思います。アイデア?

4

4 に答える 4

4

ナチュラルテーブルエイリアスを使用したのは私だけでしたPerson_overcomes_obstacle

これには、リレーショナル除算クエリが必要です。

Person_overcomes_obstacle内の障害物と一致するレコードをカウントして、2つの数字が一致するものを返すか、別の方法で、克服していない障害物がない人を見つけることができます。

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
    )
)
于 2010-07-18T21:38:16.137 に答える
3
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)
于 2010-07-18T21:25:14.580 に答える
1

使用する:

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、いずれかのクエリからカウントを実行して、記録されたすべての障害を完了した人の数を知ることができます。

于 2010-07-18T22:25:22.670 に答える
1

このSELECTは、誰も克服していない障害の数を返す必要があります。カウントがゼロの場合、すべての障害は少なくとも1人の人によって克服されています。

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)

編集:コメントで指摘されているように、上記の2つのクエリは、誰も克服していない障害がないことを証明するだけであり、1人の個人がすべての障害を克服したことを証明するものではありません。

それはさておき、 Personテーブルにクエリを実行しなくても、1人のユーザーがすべての障害を克服したことを証明できるはずです。

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)
于 2010-07-18T21:31:44.630 に答える