概要
SQL パズル20 テスト結果 解法1の学習メモです。
Exists述語を使った解法です。
要件
全てのcomp_dateに値が入っている科目の情報のみを取得する。
→comp_dateに対して、nullが一つも存在しない科目を取得する。
DDL
drop table if EXISTS TestResults;
create table TestResults(
test_name CHAR(20) not null,
test_step integer not null,
comp_date Date,
primary key(test_name,test_step)
);
INSERT INTO TestResults VALUES('読解', 1, '2006-03-10');
INSERT INTO TestResults VALUES('読解', 2, '2006-03-12');
INSERT INTO TestResults VALUES('数学', 1, NULL);
INSERT INTO TestResults VALUES('数学', 2, '2006-03-12');
INSERT INTO TestResults VALUES('化学', 1, '2006-03-08');
INSERT INTO TestResults VALUES('化学', 2, '2006-03-12');
INSERT INTO TestResults VALUES('化学', 3, '2006-03-15');
答え
-- テスト結果 その1 EXISTS 全量化
SELECT DISTINCT test_name
FROM TestResults AS T1
WHERE NOT EXISTS (SELECT *
FROM TestResults AS T2
WHERE T1.test_name = T2.test_name
AND T2.comp_date IS NULL);
-- サブクエリ内
-- 科目同士の組み合わせ(自己結合)でcomp_date=nullのレコードを取得
SELECT T1.*
FROM TestResults AS T2,TestResults AS T1
WHERE T1.test_name = T2.test_name
AND T2.comp_date IS NULL
;
-- comp_date != nullが一つも存在しない科目のレコードを取得
-- 全称量化の二重否定
SELECT *
FROM TestResults AS T1
WHERE NOT EXISTS (SELECT *
FROM TestResults AS T2
WHERE T1.test_name = T2.test_name
AND T2.comp_date IS NULL);
参考
SQLパズル p88
SQLパズル サポートページ
https://mickindex.sakura.ne.jp/database/db_support_sqlpuzzle.html#LocalLink-p20
達人に学ぶSQL徹底指南書第2版 p90 Exists述語の使い方 肯定↔️二重否定の変換に慣れる
Distinct
https://www.postgresql.jp/docs/9.5/queries-select-lists.html
EXISTS述語
https://www.postgresql.jp/document/7.3/user/functions-subquery.html
github 差分