Home実験室 − No.0057


        No.0057(SQL)
        平均を出す(AVG関数、GROUP BY句)

■環境
  □OS: Windows XP Professional SP3
  □Oracle: Oracle Database 11g R2 (Standard)
  □OSログインユーザ: ORA_DBAグループ
  □Oracleユーザ: dicdic(実験用ユーザー) → 実験環境構築スクリプト

■実験
  0. 実験ユーザー「dicdic」でコネクトする。

SQL> conn dicdic/Oracle11g 接続されました。 SQL>



  1. 入学後に死んでしまった人(在籍区分コード=13)が2人いる。

SQL> SELECT 氏名 FROM TT01_学生 Where 在籍区分コード='13'; 氏名 ---------------------------------------- 坂東 徳男 岩井 尚美 SQL>



  2. 【AVG関数】
     グループ関数の一つであるAVG関数は、平均を算出することができる。
     死んでしまった2人のTOEICの平均点を出してみよう。
     下のように、690点と出た。果たして、この数字は本当か....。

SQL> SELECT AVG(TOEIC) FROM TT01_学生 Where 在籍区分コード='13'; AVG(TOEIC) ---------- 690 SQL>



  3. この二人、よく見ると1人は未受験のようだ。
     つまり、AVG関数はデフォルトで、NULLを除外して平均を出す。
     この算出の仕方が有難いのか、有難くないのかは、ビジネスシーンによって変わってくるので要注意。

SQL> SELECT 氏名,TOEIC FROM TT01_学生 Where 在籍区分コード='13'; 氏名 TOEIC ---------------------------------------- ---------- 坂東 徳男 690 岩井 尚美 SQL>



  4. では、Nullを0として扱って平均を出すにはどうするだろう?
     関数のネストになるので多少判りづらいが、NVL関数を使えばよい。(NVL関数についてはこちら)

SQL> SELECT AVG(NVL(TOEIC,0)) FROM TT01_学生 Where 在籍区分コード='13'; AVG(NVL(TOEIC,0)) ----------------- 345 SQL>



  5. 【GROUP BY句】
     上記1〜4の例では、平均点を出す範囲をWhere句で指定したが、1年生の平均、2年生の平均....と、
     ケースごとにSQL文を一つ一つ作っていては大変。そこで、GROUP BY句というのを使える。
     グループとしてまとめる単位を指定できるのだ。
     血液型ごとのTOEICの平均点を出してみよう。.....おっと、しかしこれではよくわからん。

SQL> SELECT AVG(TOEIC) FROM TT01_学生 GROUP BY 血液型; AVG(TOEIC) ---------- 571.272618 554.561331 575.940299 549.130372 SQL>



  6. 5.の例では、算出された平均点がどのグループに対応しているのかまったくわからない。
     行ヘッダをつけたければ、血液型の列もSelectすればよい。

SQL> SELECT DECODE(血液型,1,'A',2,'B',3,'O',4,'AB'),AVG(TOEIC) FROM TT01_学生 GROUP BY 血液型; DE AVG(TOEIC) -- ---------- A 571.272618 B 554.561331 AB 575.940299 O 549.130372 SQL>



  7. もう少し改良。ソートしてみた。

SQL> SELECT DECODE(血液型,1,'A',2,'B',3,'O',4,'AB'),AVG(TOEIC) FROM TT01_学生 GROUP BY 血液型 ORDER BY 血液型; DE AVG(TOEIC) -- ---------- A 571.272618 B 554.561331 O 549.130372 AB 575.940299 SQL>



  8. さらに改良。四捨五入してみた。

SQL> SELECT DECODE(血液型,1,'A',2,'B',3,'O',4,'AB'),ROUND(AVG(TOEIC),1) FROM TT01_学生 GROUP BY 血液型 ORDER BY 血液型; DE ROUND(AVG(TOEIC),1) -- ------------------- A 571.3 B 554.6 O 549.1 AB 575.9 SQL>



  9. さらに改良。未受験者の得点を0点とした平均点も併記してみた。

SQL> SELECT DECODE(血液型,1,'A',2,'B',3,'O',4,'AB'), 2 ROUND(AVG(TOEIC),1),ROUND(AVG(NVL(TOEIC,0)),1) 3 FROM TT01_学生 GROUP BY 血液型 ORDER BY 血液型; DE ROUND(AVG(TOEIC),1) ROUND(AVG(NVL(TOEIC,0)),1) -- ------------------- -------------------------- A 571.3 364.9 B 554.6 347.8 O 549.1 364 AB 575.9 372.2 SQL>



  10. さらに改良。列ヘッダを判り易くしてみた。

SQL> SELECT DECODE(血液型,1,'A',2,'B',3,'O',4,'AB') 血液型, 2 ROUND(AVG(TOEIC),1) 平均点,ROUND(AVG(NVL(TOEIC,0)),1) "平均点(未受験は0点扱い)" 3 FROM TT01_学生 GROUP BY 血液型 ORDER BY 血液型; 血 平均点 平均点(未受験は0点扱い) -- ---------- ----------------------- A 571.3 364.9 AB 575.9 372.2 B 554.6 347.8 O 549.1 364 SQL>



  11. うーん。上の例だと血液型の列ヘッダが気に食わない。こういう場合、私ならスペースをパディングしちゃう。
     AB型が最上行に表示されちったけど....。まぁヨシとしよう。

SQL> SELECT RPAD(DECODE(血液型,1,'A',2,'B',3,'O',4,'AB'),3,' ') 血液型, 2 ROUND(AVG(TOEIC),1) 平均点,ROUND(AVG(NVL(TOEIC,0)),1) "平均点(未受験は0点扱い)" 3 FROM TT01_学生 GROUP BY 血液型 ORDER BY 血液型; 血液型 平均点 平均点(未受験は0点扱い) ------ ---------- ----------------------- AB 575.9 372.2 A  571.3 364.9 B  554.6 347.8 O  549.1 364 SQL>





    【PR】    Oracle実験室監修  『Oracleアーキテクチャ鳥瞰図』 PDF  (Oracleのアーキテクチャを一目で俯瞰できるイラスト)  


Home実験室 − No.0057

© 2011-2011   Amateur Laboratory of ORACLE
inserted by FC2 system