hive求解中位数的几种方法

  • 前言
  • 两种解法
    • 解法1:利用中位数的位次特征
    • 解法2:利用升序与降序的差值
      • 解法2.1:
  • 延伸问题:频次+分数
  • 参考文章

前言

假设我们有一张学生成绩表student_score,里面有三个字段:学生id:student_id,班级id:class_id,成绩:score,主键为student_id。现在让你求出每个班级学生成绩的中位数。

虽然hive里有内置的percentile()和percentile_approx()函数直接求解分位数,但在面试中,面试官老爷大概率不会让你直接就这么写,而是在你自信满满刷刷刷写完之后告诉你“哦,我们不能用内置函数”。

两种解法

谈到中位数,自然而然容易想到要先排序,然后根据个数的奇偶,如果是奇数个就取中间一位,如果是偶数就取中间两位的平均。关于排序,我们可以使用窗口函数row_number()1,关于奇偶,我们不妨看看奇偶个数有没有共性。

如果总共有n个数,当n=5时,n/2=2.5,我们想要的输出是第3位;当n=6时,n/2=3,我们想要的输出是第3位和第4位的平均,那么可以发现:无论奇偶,中位数必然是在n/2和n/2+1之间的数(包含两端)的平均

由此可以产生第一种解法

解法1:利用中位数的位次特征

先取出每个班级成绩排序以及总数,形成表t,再限制中位数是在n/2和n/2+1之间的数(包含两端)的平均2

select class_id,avg(score) as score_median
from(select class_id,score,row_number() over (partition by class_id order by score asc) as score_rank,count(student_id) over(partition by class_id) as student_numfrom student_score)t
where score_rank between student_num/2 and student_num/2+1
group by class_id

解法2:利用升序与降序的差值

观察如下升序编号和降序编号可以发现,当n为奇数时,中位数对应的升序编号和降序编号的差值为0,当n为偶数时,中位数对应的升序编号和降序编号的差值为1或-13

  • 奇数情况

  • 偶数情况


那么通过限定升序编号和降序编号的差值为1,-1或者0,我们可以有如下写法:

select class_id,avg(score) as score_median
from(select class_id,score,row_number() over (partition by class_id order by score asc) as score_rank_asc,row_number() over (partition by class_id order by score desc) as score_rank_descfrom student_score)t
where (score_rank_asc- score_rank_desc) in (1,-1,0)
group by class_id

但是解法2有一个问题,我们知道row_number处理相同值的时候会随机给一个rank,所以对于不同student_id的相同分数,可能会产生不同的rank,具体来说:

这时候奇数情况也会存在升序编号和降序编号的差值为1或者-1,就会造成错误的输出。此时可以通过限定主键的方式来使得row_number对于相同分数的不同学生,降序排和升序排的名次在逻辑上是相同的(即保证五个人升序排我是第三名,降序排我也是第三名)。

解法2.1:

select class_id,avg(score) as score_median
from(select class_id,score,row_number() over (partition by class_id order by score asc student_id asc) as score_rank_asc,row_number() over (partition by class_id order by score desc student_id desc) as score_rank_descfrom student_score)t
where (score_rank_asc- score_rank_desc) in (1,-1,0)
group by class_id

延伸问题:频次+分数

假设现在我们没有每个人的成绩了,只有每个班级的成绩及频次,即问题转换为:学生成绩表student_score,里面有三个字段:班级id:class_id,成绩:score,频次:frequency。现在让你求出每个班级学生成绩的中位数。

这时候仍然可以考虑升序和降序的频数累积和,两个数都需要大于等于总数一半,即为中位数4

由此有如下写法:

selectclass_id ,avg(score) as score_median
from
(select class_id,score,sum(frequency) over(partition by class_id order by score asc) as total_asc,sum(frequency) over(partition by class_id order by score desc) as total_desc,sum(frequency) over(partition by class_id ) as total_numfrom student_score
)t
where total_asc>=total_num/2
and total_desc>=total_num/2
group by class_id

参考文章


  1. SQL窗口函数 ↩︎

  2. 中位数特征 ↩︎

  3. 正序倒序差值 ↩︎

  4. 延伸问题 ↩︎

hive求解中位数的几种方法相关推荐

  1. MATLAB求解线性方程组的八种方法

    MATLAB求解线性方程组的八种方法 求解线性方程分为两种方法–直接法和迭代法 常见的方法一共有8种 直接法 Gauss消去法 Cholesky分解法 迭代法 Jacobi迭代法 Gauss-Seid ...

  2. python线性方程组求解_python求解方程组的三种方法

    python求解方程组的三种方法: Numpy求解方程组x + 2y = 3 4x + 5y = 6 当然我们可以手动写出解析解,然后写一个函数来求解,这实际上只是用 Python 来单纯做" ...

  3. 第二十二章:求解素数的N种方法

    求解素数的N种方法 一.质数和合数 质数: 质数又称**素数**.指在一个大于 1的自然数中,除了 1和此整数自身外,不能被其他自然数整除的数.换句话说,只有两个正因数(1和自己)的自然数即为质数. ...

  4. 算法导论中求解时间复杂度的三种方法

    这一章讲的是递归式(recurrence),递归式是一组等式或不等式,它所描述的函数是用在更小的输入下该函数的值来定义的. 本章讲了三种方法来解递归式,分别是代换法,递归树方法,主方法. 1.代换法( ...

  5. Excel规划求解Solver:三种方法的区别

    Excel Solver作为常用的最优解解决工具,在选择解决方法(solving method)的时候有三种选项,这三种选项有什么区别?什么时候该选择哪种方法?在本文做综合解释 目录 1. GRG N ...

  6. Matlab求解线性方程组的三种方法(wzl)

    A=[3 12 1;12 0 2;0 2 3]; b=[2.36;5.26;2.77]; %第一种方法 A\b %当无穷多解时,会使得解中尽量多0 %可算无解方程组%第二种方法 pinv(A)*b % ...

  7. python求列表的中位数_python中获取中位数的两种方法

    普通方法: 对列表进行排序,然后根据长度为奇数或者偶数的不同情况计算中位数 def huahua(x): length = len(x) print(length) x.sort() print(x) ...

  8. 求解最短路问题的几种方法总结

    1.spfa求单源最短路,链式前向星存图, 时间复杂度o(kE) k是常数,大多数情况下为2. #include <stdio.h> #include <queue> #inc ...

  9. matlab方程近似求根,matlab求解方程的几种方法

    k=i-1; xk=x(i);[(i-1) xk yk piancha xdpiancha] return ; end end if i>gxmax disp('请注意:迭代次数超过给定的最大值 ...

最新文章

  1. 【机器学习】基于LDA主题模型的人脸识别专利分析
  2. 微型计算机普遍使用的编码是,微型计算机中普遍使用的字符编码是什么吗
  3. 37岁跳槽去阿里 p8_36岁阿里p8发帖:手下12个p7,17个p6,亲自写代码毫无中年危机...
  4. jquery中点击切换的实现
  5. PHP大数据处理【转】
  6. js判断函数是否存在
  7. windows pip命令不见了_Python中Pygame以及pip的下载与安装
  8. java-前端之js
  9. python 进行一元线性回归并输出相关结果_荐一元线性回归利用最小二乘法求解原理代码及案例...
  10. android 之 Dialog
  11. vue分页组件重置到首页问题
  12. 编程基本功:正常运行的代码,你看明白能做什么?不如解决几个简单BUG
  13. Latex中导入VISIO图片
  14. Junit 4 的 @Before 和 @BeforeClass 对比 Junit 5 @BeforeEach 和 @BeforeAll
  15. Git 初接触 (四) Git的分支操作
  16. Python随记(27)bs4爬取豆瓣250
  17. TOM邮箱|选出好用的邮箱让你事半功倍
  18. 互动编程习作——表现随机行为及牛顿运动学
  19. 老板喜欢的高绩效哪里来?
  20. IDEA创建java项目src下没有办法创建包文件/MAVEN模块名变灰且模块多道横杠

热门文章

  1. 斐波那契数列之不死神兔---------说白了就是递归的应用
  2. StackEdit Windows本地服务器搭建
  3. 0x80073712_Win10系统更新老失败,提示错误代码0x80073712,这种问题应该如何解决?...
  4. php 5.3 register_globals,PHP中register_globals参数设置
  5. ARP静态绑定技术-快速绑定
  6. VIVO U3破解密码
  7. 推荐几个IDEA插件
  8. 朗读评价语言集锦_课堂评价语言集锦
  9. android微信二维码收款hook,【第一篇】【安卓微信】HOOK微信发消息,当HOOK遇上HOOK。...
  10. html如何调节透明度,CSS 如何设置一个元素的透明度呢?