欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SQL求众数、中值(Having)

程序员文章站 2022-05-29 15:48:17
...

众数

众数:顾名思义就是一组数据中出现次数最多的数。
现有Graduates表:

Graduates表
| name   | income |
+--------+--------+
| 桑普森 | 400000 |
| 迈克   |  30000 |
| 怀特   |  20000 |
| 阿诺德 |  20000 |
| 史密斯 |  20000 |
| 劳伦斯 |  15000 |
| 哈德逊 |  15000 |
| 肯特   |  10000 |
| 贝克   |  10000 |
| 斯科特 |  10000 |

查找众数:

select income from graduates group by income 
having count(*) >= all(select count(*) from graduates group by income);

注意:当income列有值为null时,用谓词all可能会出现unknown的情况。这种情况是我们不愿意看到的。
可以用极值函数来代替,避免这种情况的发生。

select income from graduates group by income 
having count(*) >= max(select count(*) from graduates group by income);

中位数

当平均值不可信时,与众数一样经常被用到的另一个指标是中位数 (median)。它指的是将集合中的元素按升序排列后恰好位于正中间 的元素。如果集合的元素个数为偶数,则取中间两个元素的平均值作 为中位数。
以Graduates表为例求中位数:

--如果中间值有两个,则求平均值。
select avg(income) from (
select g1.income from graduates g1 ,graduates g2
group by g1.income 
having 
/*我是这样理解的。
count(*)/2可以看作是一组数据排序后的中间的值(组数据长度为偶数则中间值有两个),(sum(case when g1.income >= g2.income then 1 else 0 end) >= count(*)/2) 
可以理解为判断该值是不是中间值的之前的最大值,如果是则sum的结果必定是大于等于中间值的。
(sum(case when g1.income <= g2.income then 1 else 0 end) >= count(*)/2)
同样,可以理解为判单g1.incom是不是中间值之后的数据中最小的值,如果大于g1.incom的值超过了count(*)/2,则该值必定小于等于中间值。
两个条件同时满足则就是中间值(数据组中个数为偶数则中间值有两个)。
*/
	(sum(case when g1.income >= g2.income then 1 else 0 end) >= count(*)/2)
	and
	(sum(case when g1.income <= g2.income then 1 else 0 end) >= count(*)/2)
) as t_graduates;

特征函数:用来判断各个元素是否属于满足某个条件的结合。
或则从定义了的集合的角度来说,他是定义函数。