勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

MySQLで指定したカラムの中央値を抽出する方法

  MySQL データベース

MySQLで指定したカラムの中央値を抽出したいというケースがあった。MariaDBの10.3.3以上だと中央値を求めるMEDIAN()という関数が実装されているらしいが、当方の環境はMySQL8.0.32のため実装されておらず、SQL文で何とかしないといけないっぽい。以下に対応方法をメモ。

 

テーブル構造

mysql> SHOW COLUMNS FROM `test_table`;
+-------+------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra          |
+-------+------+------+-----+---------+----------------+
| id    | int  | NO   | PRI | NULL    | auto_increment |
| score | int  | NO   |     | NULL    |                |
+-------+------+------+-----+---------+----------------+

 

データ内容

mysql> SELECT * FROM `test_table` ORDER BY `score` DESC;
+----+-------+
| id | score |
+----+-------+
|  1 |   100 |
|  4 |    80 |
|  5 |    70 |
| 10 |    70 |
|  3 |    60 |
|  7 |    55 |
|  6 |    50 |
|  2 |    40 |
|  8 |    20 |
|  9 |    20 |
+----+-------+

 

対応方法

SQL文

SET @row_index := -1;
SELECT AVG(subq.score) AS median_value 
FROM 
    (
        SELECT @row_index:=@row_index + 1 AS row_index, score
        FROM test_table
        ORDER BY score
    ) AS subq
WHERE subq.row_index IN (FLOOR(@row_index / 2), CEIL(@row_index / 2));

出力結果

上記SQL文を実行すると以下が出力される筈。全データの行数が偶数になるため、id3の60とid7の50の平均値が出力される。

+--------------+
| median_value |
+--------------+
|      57.5000 |
+--------------+

全データの行数が奇数の場合

以下のように全データの行数が奇数行の場合、

mysql> SELECT * FROM `test_table` ORDER BY `score` DESC;
+----+-------+
| id | score |
+----+-------+
|  1 |   100 |
|  4 |    80 |
|  5 |    70 |
| 10 |    70 |
|  3 |    60 |
|  7 |    55 |
|  6 |    50 |
|  2 |    40 |
| 11 |    30 |
|  8 |    20 |
|  9 |    20 |
+----+-------+

前述のSQL文を実行すると以下が出力される筈。

+--------------+
| median_value |
+--------------+
|      55.0000 |
+--------------+

こちらはid7の55がそのまま出力された。

 

参考サイト

https://sebhastian.com/mysql-median/

 - MySQL データベース

  関連記事

MySQLのintのカラムで2147483647の値
MySQLのintのカラムで2147483647の値

MySQLでintのカラムに数値を入れると「2147483647」という値になっ ...

MySQLで月別に集計を行う。あと日付時刻関数。
MySQLで月別に集計を行う。あと日付時刻関数。

現在進行形でやっているデータ集計系だけど 新たな発見があったのでメモ。 ■日付時 ...

MySQLにてUUIDを発行しプライマリキー(主キー)にする方法
MySQLにてUUIDを発行しプライマリキー(主キー)にする方法

普段MySQLでプライマリキー(主キー)を使う場合、オートインクリメントを利用し ...

PHP / MySQLで2038年問題の対策
PHP / MySQLで2038年問題の対策

先日打ち合わせの際に「タイムスタンプを使ってユニークキーに云々~~」といったよう ...

MySQLでdatetime型にもインデックスを使用して高速化を図る方法
MySQLでdatetime型にもインデックスを使用して高速化を図る方法

ログ関連のデータを格納するテーブルがあり、集計を行う際に非常に時間がかかった。レ ...