目次
平均を取得するAVG関数
SQLでレコードの平均値を取得したい場合は「AVG関数」を使います。
使う場合は、次のように記述しましょう。
SELECT AVG(カラム名) FROM テーブル名;
実際に、次のようなテーブルを作成して確認してみます。
mydb=# CREATE TABLE score_tb(class varchar(10), name varchar(20), score integer); CREATE TABLE
なお、ここでは「PostgreSQL」を使用しました。
インストール方法や使い方を知りたい場合は、下記の記事を参考にしてみてください。
【関連記事】
▶︎PostgreSQLのインストールからテーブル作成まで解説【初心者向け】
そして、テーブル内には次のデータを追加しました。
mydb=# INSERT INTO score_tb VALUES('1-1', 'Satou', 67); INSERT 0 1 mydb=# INSERT INTO score_tb VALUES('1-2', 'Yamada', 73); INSERT 0 1 mydb=# INSERT INTO score_tb VALUES('1-1', 'Tanaka', 89); INSERT 0 1 mydb=# INSERT INTO score_tb VALUES('1-3', 'Yokota', 56); INSERT 0 1 mydb=# INSERT INTO score_tb VALUES('1-2', 'Itou', 91); INSERT 0 1
この全データに対してAVG関数で平均を取得してみましょう。
mydb=# SELECT AVG(score) FROM score_tb; avg --------------------- 75.2000000000000000 (1 row)
実際に計算機で計算しても「75.2」となり、ちゃんと平均が取得できているのがわかります。
AVG関数は条件を指定しても取得可能です。
平均を条件付きで取得する方法
次に、条件を指定しつつデータを取得する方法を見ていきましょう。
特定の条件に一致するデータの平均を取得(WHERE)
今回作成したテーブルの例だと「指定したcalssの平均値を取得したい」という場合もあるでしょう。
こんな風に特定の条件で平均を求めたい場合は、「WHERE句」を使って指定します。
記述方法は次の通りです。
SELECT AVG(カラム名) FROM テーブル名 WHERE 条件文;
サンプルで平均の求め方を見てみましょう。
mydb=# SELECT AVG(score) FROM score_tb WHERE class = '1-1'; avg --------------------- 78.0000000000000000 (1 row)
ここでは、classカラムが「1-1」であるデータの平均値を取得しました。
計算結果を確認してみると、ちゃんと平均を取得できているのがわかります。
複数行のデータの平均を取得(GROUP BY)
「classが1-1、1-2、1-3ごとにまとめて平均を取得したい」場合は、「GROUP BY句」が使えます。
記述方法は次の通りです。
SELECT AVG(カラム名) FROM テーブル名 GROUP BY カラム名;
こちらもサンプルコードで表示を確認してみましょう。
mydb=# SELECT class, AVG(score) FROM score_tb GROUP BY class; class | avg -------+--------------------- 1-2 | 82.0000000000000000 1-3 | 56.0000000000000000 1-1 | 78.0000000000000000 (3 rows)
平均値だけだとどのclassのデータかわかりづらいため、SELECTに「class」を追加しました。
このようにclassごとに平均が求められました。
ただ、classが「1-2」「1-3」「1-1」と言う順番になっていて少し気持ち悪いですよね。
classの順番を変更したい場合は「ORDER BY句」も組み合わせれば次のようにきれいに表示できますので参考までに。
mydb=# SELECT class, AVG(score) FROM score_tb GROUP BY class ORDER BY class; class | avg -------+--------------------- 1-1 | 78.0000000000000000 1-2 | 82.0000000000000000 1-3 | 56.0000000000000000 (3 rows)
複数列の平均を取得する
複数列の平均を取得する方法を確認してみましょう。
先ほどのテーブルに「point」カラムを追加し、それぞれのデータに値を次のように挿入しました。
mydb=# SELECT * FROM score_tb; class | name | score | point -------+--------+-------+------- 1-1 | Satou | 67 | 133 1-2 | Yamada | 73 | 173 1-1 | Tanaka | 89 | 220 1-3 | Yokota | 56 | 101 1-2 | Itou | 91 | 149 (5 rows)
このテーブルの「score」と「point」カラムの平均をclassごとに取得してみます。
mydb=# SELECT class, AVG(score) AS score_ave, AVG(point) AS point_ave FROM score_tb GROUP BY class ORDER BY class; class | score_ave | point_ave -------+---------------------+---------------------- 1-1 | 78.0000000000000000 | 176.5000000000000000 1-2 | 82.0000000000000000 | 161.0000000000000000 1-3 | 56.0000000000000000 | 101.0000000000000000 (3 rows)
このように「score」と「point」カラムの平均を取得できました。
また、「複数のカラムの値を合計した平均」を取得したい場合は、AVG関数を使わずに次のような記述で取得可能です。
mydb=# SELECT class, name, score, point, (score+point)/2 AS avg FROM score_tb GROUP BY class, name, score, point; class | name | score | point | avg -------+--------+-------+-------+----- 1-2 | Yamada | 73 | 173 | 123 1-1 | Satou | 67 | 133 | 100 1-3 | Yokota | 56 | 101 | 78 1-2 | Itou | 91 | 149 | 120 1-1 | Tanaka | 89 | 220 | 154
純粋に「score」と「point」カラムの値を足して2で割っています。
これで2つ(複数)のカラムの平均値を求められます。
ただし、データにNULLが入っていると平均値もNULLになってしまうため、この辺りは別途処理が必要です。
詳しくは「平均の取得でNULLがある場合」で解説します。
平均値の小数点以下を切り捨てる方法
AVG関数を使って平均を取得すると、小数点以下まで表示されていました。
この小数点以下を切り捨てる場合は「TRUNC関数」を使います。(MySQLの場合は「TRUNCATE関数」になります)
実際に小数点以下の表示がどのようになるのか確認してみましょう。
今度は、「score_tb」テーブルに「height」カラムを追加しました。
mydb=# SELECT * FROM score_tb; class | name | score | point | height -------+--------+-------+-------+-------- 1-1 | Satou | 67 | 133 | 182.4 1-1 | Tanaka | 89 | 220 | 173.7 1-3 | Yokota | 56 | 101 | 175.9 1-2 | Itou | 91 | 149 | 170.3 1-2 | Yamada | 74 | 173 | 179.6 (5 rows)
この「height」カラムの平均値を「class」カラムごとに取得してみます。
mydb=# SELECT class, AVG(height) FROM score_tb GROUP BY class; class | avg -------+-------- 1-2 | 174.95 1-3 | 175.9 1-1 | 178.05 (3 rows)
このように、小数点以下の値まで取得できました。
では、TRUNC関数を使って平均を求めてみます。
mydb=# SELECT class, TRUNC(AVG(height)) FROM score_tb GROUP BY class; class | trunc -------+------- 1-2 | 174 1-3 | 175 1-1 | 178 (3 rows)
小数点以下が切り捨てられ、整数で値が表示されているのがわかります。
平均値を四捨五入する方法
小数点以下を切り捨てではなく、四捨五入したい場合は「ROUND関数」を使いましょう。
mydb=# SELECT class, ROUND(AVG(height)) FROM score_tb GROUP BY class; class | round -------+------- 1-2 | 175 1-3 | 176 1-1 | 178 (3 rows)
このように四捨五入した値が取得できます。
平均の取得でNULLがある場合
AVG関数でカラムの値を取得する際に「NULL」が入っている場合、NULLは無視されます。
こちらもサンプルで表示を確認してみましょう。
データに「score」カラムがNULLのデータを追加しました。
mydb=# SELECT * FROM score_tb; class | name | score | point | height -------+-----------+-------+-------+-------- 1-1 | Satou | 67 | 133 | 182.4 1-1 | Tanaka | 89 | 220 | 173.7 1-3 | Yokota | 56 | 101 | 175.9 1-2 | Itou | 91 | 149 | 170.3 1-2 | Yamada | 74 | 173 | 179.6 1-3 | Hashimoto | | 15 | 154.7 (6 rows)
では、次の記述で平均値を取得してみましょう。
mydb=# SELECT class, AVG(score) FROM score_tb GROUP BY class; class | avg -------+--------------------- 1-2 | 82.5000000000000000 1-3 | 56.0000000000000000 1-1 | 78.0000000000000000 (3 rows)
このように、NULLは無視されて平均が求められています。
ただし、データがNULLしかない場合は平均値もNULLになります。
mydb=# SELECT class, AVG(score) FROM score_tb GROUP BY class; class | avg -------+--------------------- 1-2 | 82.5000000000000000 1-4 | 1-3 | 56.0000000000000000 1-1 | 78.0000000000000000 (4 rows)
では「複数列の平均を取得する」で解説した「score」と「point」カラムにNULLがあった場合の平均の求め方も見ていきましょう。
これを実現する1つの方法に「COALESCE関数」を使う方法があります。
COALESCE関数は、NULLの代替値を取得する関数です。
詳しい内容は次の記事で解説していますので、知りたい方は参考にしてみてください。
【関連記事】
▶︎SQL coalesce 値がNULLの場合の代替値を返す 簡易版のNVLやNULLIFが使えるDBもあり
ではサンプルで表示を確認してみます。
mydb=# SELECT class, name, score, point, COALESCE((score+point)/2, score, point) AS avg FROM score_tb GROUP BY class, name, score, point; class | name | score | point | avg -------+-----------+-------+-------+----- 1-3 | Hashimoto | | 15 | 15 1-1 | Satou | 67 | 133 | 100 1-3 | Yokota | 56 | 101 | 78 1-2 | Itou | 91 | 149 | 120 1-4 | Minami | | 155 | 155 1-1 | Tanaka | 89 | 220 | 154 1-2 | Yamada | 74 | 173 | 123 (7 rows)
このように、scoreがNULLである「Hashimoto」と「Minami」の平均値も取得できていますね。
AVG関数を使う場合は問題ありませんが、そうでない場合はNULLを考慮したSQLクエリを記述しましょう。
まとめ
SQLの平均に関する関数や取得方法について解説しました。
DB操作でデータの平均を求める機会は多くあると思います。
ぜひこの記事で平均を取得する方法の参考にしてください!