SQL 指南書集 目次 - ray88’s diary
■COUNT(*)とCOUNT(列名)の違い
・COUNT関数の使用法にはCOUNT(*)とCOUNT(列名)がある
・COUNT(*) はNULLを数えるのに対し、 COUNT(列名)は他の集計関数と同様に NULL除外して集計する
※つまり、COUNT(*)は全行を数えるのに対しCOUNT(列名)はそうではない
(例)NULL値しか含まないテーブルに以下のSELECT文を実行する
--NULLを含む列に適用した場合、COUNT(*)とCOUNT(列名)の結果は異なる SELECT COUNT(*),COUNT(col_1) FROM null_tbl;
出力結果
■例題
学生のレポート提出日を記録するテーブル「students」がある。
学生がレポートを未提出の間の提出日列の値はNULL。提出すると提出日が入る。
このテーブルより所属するすべての学生が提出済の学部(理学部と経済学部)を求める
【考え方】
STEP1:学部をキーにGROUP BY句を使用して下図のような部分集合を作る
STEP2:作成した4つの部分集合のうち、抽出するのはS1(理学部)とS4(経済学部)
STEP3:S1(理学部)とS4(経済学部)の2つの集合が共有していて他の集合がもっていない性質を探す
→「COUNT(*)とCOUNT(sbmt_date)」が一致する(S3とS4はNULLを含むため一致しない)
以上より、以下回答のSQL文となる
【回答例】
その1:COUNT関数の利用
--提出日にNULLを含まない学部を選択する その1:COUNT関数の利用 SELECT dpt FROM students GROUP BY dpt HAVING COUNT(*) = COUNT(sbmt_date);
その2:CASE式の利用
※Case式は提出日がNULLでない行については1,NULLの行については0というフラグを立てている
--提出日にNULLを含まない学部を選択する その1:COUNT関数の利用 SELECT dpt FROM students GROUP BY dpt HAVING COUNT(*) = SUM(CASE WHEN sbmt_date IS NOT NULL THEN 1 ELSE 0 END);
■応用例題
全員が9月中にレポート提出済みの学部を抽出する
※経済学部のみが抽出される。
理学部は100番の学生が10月に提出しているため除外
文学部と工学部は未提出の学生がいるため除外
【回答】
解答例1
/* 演習問題2:特性関数の練習(p.293) 全員が9 月中に提出済みの学部を選択する その1:BETWEEN 述語の利用 */ SELECT dpt FROM Students GROUP BY dpt HAVING COUNT(*) = SUM(CASE WHEN sbmt_date BETWEEN '2005-09-01' AND '2005-09-30' THEN 1 ELSE 0 END);
解答例2
/* 演習問題2:特性関数の練習(p.293) 全員が9 月中に提出済みの学部を選択する その2:EXTRACT 関数の利用 */ SELECT dpt FROM Students GROUP BY dpt HAVING COUNT(*) = SUM(CASE WHEN EXTRACT (YEAR FROM sbmt_date) = 2005 AND EXTRACT (MONTH FROM sbmt_date) = 09 THEN 1 ELSE 0 END);
【参考】テーブル作成SQL
null_tbl
CREATE TABLE null_tbl (col_1 VARCHAR(16)); INSERT INTO null_tbl VALUES(NULL); INSERT INTO null_tbl VALUES(NULL); INSERT INTO null_tbl VALUES(NULL);
students
/* NULL を含まない集合を探す */ CREATE TABLE Students (student_id INTEGER PRIMARY KEY, dpt VARCHAR(16) NOT NULL, sbmt_date DATE); INSERT INTO Students VALUES(100, '理学部', '2005-10-10'); INSERT INTO Students VALUES(101, '理学部', '2005-09-22'); INSERT INTO Students VALUES(102, '文学部', NULL); INSERT INTO Students VALUES(103, '文学部', '2005-09-10'); INSERT INTO Students VALUES(200, '文学部', '2005-09-22'); INSERT INTO Students VALUES(201, '工学部', NULL); INSERT INTO Students VALUES(202, '経済学部', '2005-09-25');