MySQL 求眾數、稀疏數
資料表
假設有 student 表,資料如下:
+----+------+-------+
| id | name | score |
+----+------+-------+
| 1 | 劉備 | 90 |
| 2 | 曹操 | 90 |
| 3 | 孫權 | 90 |
| 4 | 劉表 | 50 |
| 5 | 劉封 | 30 |
| 6 | 張飛 | NULL |
+----+------+-------+
建表語句如下:
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`score` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
問題 1 :求出現次數最多的分數、出現次數最少的分數
(1)select score from student where score is not null group by score order by count(*) desc limit 1; -- 出現次數最多的分數
+-------+
| score |
+-------+
| 90 |
+-------+
(2)select score from student where score is not null group by score order by count(*) asc limit 1; -- 出現次數最少的分數
+-------+
| score |
+-------+
| 50 |
+-------+
問題 2:求出現次數最多的姓、出現次數最少的姓
(1)select left(name,1) from student group by left(name,1) order by count(*) desc limit 1; -- 出現次數最多的姓
+--------------+
| left(name,1) |
+--------------+
| 劉 |
+--------------+
(2)select left(name,1) from student group by left(name,1) order by count(*) asc limit 1; -- 出現次數最少的姓
+--------------+
| left(name,1) |
+--------------+
| 曹 |
+--------------+
問題 3:求出現次數最多的分數區間( 劃分為兩個區間[0, 60)、[60, 100] ,還可以劃分的更細,這裡只劃分為 2 個)、出現次數最少的分數區間
(1) select if(score<60,'[0, 60)','[60, 100]') from student where score is not null group by if(score<60,'[0, 60)','[60, 100]') order by count(*) desc limit 1; -- 出現次數最多的分數區間
+------------------------------------+
| if(score<60,'[0, 60)','[60, 100]') |
+------------------------------------+
| [60, 100] |
+------------------------------------+
(2) select if(score<60,'[0, 60)','[60, 100]') from student where score is not null group by if(score<60,'[0, 60)','[60, 100]') order by count(*) asc limit 1;-- 出現次數最少的分數區間
+------------------------------------+
| if(score<60,'[0, 60)','[60, 100]') |
+------------------------------------+
| [0, 60) |
+------------------------------------+
缺陷及改正
其實、眾數或稀疏數可能有多個,比如問題 2 中的出現次數最少的姓名不知一個,包括 孫、張、曹。
考慮到這種情況的 sql 應該這麼寫:
select left(name, 1) from student group by left(name, 1) having count(*) = (select count(*) from student group by left(name,1) order by count(*) asc limit 1);
執行 sql,得到結果集
+---------------+
| left(name, 1) |
+---------------+
| 孫 |
| 張 |
| 曹 |
+---------------+
其他問題中的情況類似。