リレーショナルデータベースに3つのテーブルがあるとしましょう。
Person {id, name}
Obstacle {id, name}
Person_overcomes_obstacle {person_id, obstacle_id}
少なくとも1人の人がすべての障害を克服したかどうかを教えてくれるクエリを書きたいと思います。アイデア?
リレーショナルデータベースに3つのテーブルがあるとしましょう。
Person {id, name}
Obstacle {id, name}
Person_overcomes_obstacle {person_id, obstacle_id}
少なくとも1人の人がすべての障害を克服したかどうかを教えてくれるクエリを書きたいと思います。アイデア?
ナチュラルテーブルエイリアスを使用したのは私だけでした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
)
)
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 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
、いずれかのクエリからカウントを実行して、記録されたすべての障害を完了した人の数を知ることができます。
この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)