- existsの引数は行の集合である。
- existsは二階の述語である。
- existsはsqlで存在量化子を使うための述語である。
- 全称量化子を存在量化子の否定で書くことができる。
条件Pを満たさない、あるx(の集合?)を取得するクエリ
select DISTINCT m1.meeting,m2.person
from Meetings m1 CROSS join meetings m2
WHERE not EXISTS(
SELECT *
from meetings m3
WHERE m1.meeting = m3.meeting
and m2.person = m3.person
)
「すべての教科が50点以上であるようなx」をとるクエリを書く。全称命題と存在命題を考えてみる。前提は以下の通りです(※数学記号の使い方が間違っていると思うので、ご指摘歓迎です、特にP(x)のなかでiを動かせるようにしているのですが、ここが微妙)。
一人の生徒に絞って考える。
\begin{flalign}
&X = \{iの点数 \}_{i={国語、算数、英語、理科}} ,x \in X \\
&P(x)= xの要素xiは50以上である(i=...)
\text すべての教科が50点以上である
&\lceil\forall xi \in X, P(xi)_{i=...}\rfloor \text { の否定は }\\
&\text すべての教科が50点以上でないxが存在しない\lceil\neg\exists xi \in X, \neg P(xi)_{i=...}\rfloor
\end{flalign}
ということになる。これを実装する。
例2
ある乗客のすべての行について(バインドに対応、この例では各乗客一行だが)
男性ならば年齢が60歳以上,女性ならば年齢が20歳以上である行の集合を取得
ポイント
・passengeridでバインド
・and で式を使用して真理値の判定を使用することで条件分岐可能
SELECT passengerid,sex,age
FROM train TS1
WHERE sex IN ('male', 'female')
AND NOT EXISTS
(SELECT *
FROM train TS2
WHERE TS2.passengerid = TS1.passengerid
AND 1 = CASE WHEN sex = 'male' AND age < 60 THEN 1
WHEN sex = 'female' AND age < 20 THEN 1
ELSE 0 END)
-- GROUP BY passengerid
-- HAVING COUNT(*) = 1
order by passengerid asc;
・existsはhavingと比較して
・パフォーマンスが良い
・平の行をとってこれる
の2点で優れている