HiveSql面试题--如何分析中位数?

目录

0 问题描述

1 问题分析

2 本题小结

3 举一反三


0 问题描述

学校每次考试完,都会有一个成绩表。例如,表中第1行表示编号为1的用户选择了C++岗位,该科目考了11001分。

问题:写一个sql语句查询每个岗位的中位数位置的范围,并且按岗位升序排序,结果如下:

解释:

  • 第1行表示C++岗位的中位数位置范围为[2,2],也就是2。因为C++岗位总共3个人,是奇数,所以中位数位置为2。
  • 第2行表示Java岗位的中位数位置范围为[1,2]。因为Java岗位总共2个人,是偶数,所以要知道中位数,需要知道2个位置的数字,而因为只有2个人,所以中位数位置为[1,2]。
  • 第3行表示前端岗位的中位数位置范围为[2,2],也就是2。因为前端岗位总共3个人,是奇数,所以中位数位置为2。

1 问题分析

(1)要求每个岗位的中位数位置的范围,需要知道每个岗位的总数

        那么,如何求每个岗位的总数呢?

      看到“每个”,就要想到用分组汇总解决这类型问题。按岗位分组(group by),使用汇总函数count()得到岗位总数。

select 岗位,count(*) as 总数from 成绩表group by 岗位;

图片

(2)岗位总数又分为奇数和偶数两种情况。

岗位数有奇数也有偶数,需要分情况进行计算,可以使用case表达式。

如何判断奇偶呢?我们可以使用%或mod函数。

奇数,就是除以2的余数为1,可以用下面两种方法表示

  • (1)  总数 % 2 = 1
  • (2)  mod(总数,2) = 1

偶数,就是除以2的余数为0,可以用下面两种方法表示

  • (1)  总数 % 2 = 0
  • (2)  mod(总数,2) = 0

再结合求中位数起始位置的关系,使用case表达式:

而case表达式中的总数是由前面使用第1步count()函数计算出来的,所以第1步要先于case语句运行,因为要把第1步的sql作为子查询

select 岗位,
(case when 总数 % 2 = 1 then (总数+1)/2 else 总数/2 end) as 起始位置,
(case when 总数 % 2 = 1 then (总数+1)/2 else 总数/2+1 end) as 结束位置
from
(select 岗位,count(*) as 总数
from 成绩表
group by 岗位) as t;

最后按岗位升序排序,用排序子句(order by)

select 岗位,
(case when 总数 % 2 = 1 then (总数+1)/2 else 总数/2 end) as 起始位置,
(case when 总数 % 2 = 1 then (总数+1)/2 else 总数/2+1 end) as 结束位置
from
(select 岗位,count(*) as 总数
from 成绩表
group by 岗位) as t
order by 岗位;

图片

2 本题小结

1.考察如何将复杂问题拆解为简单问题,可以使用多维度拆解分析方法,例如本案例中问题拆解问3步:

  • 1)将中位数位置用公式表示出来
  • 2)计算出每个岗位的总数
  • 2)分情况统计总数的奇数、偶数

2.如何用%或mod函数判断奇偶

3.每个问题,要想到分组汇总来解决

4.多条件判断问题,要想到用case表达式

5.考查sql的运行顺序和子查询

3 举一反三

以下是某班同学的科目成绩表,查询每门科目的中位数位置的范围,并且按科目升序排序。

select 科目,
(case when 总数 % 2 = 1 then (总数+1)/2 else 总数/2 end) as 起始位置,
(case when 总数 % 2 = 1 then (总数+1)/2 else 总数/2+1 end) as 结束位置
from
(select 科目,count(*) as 总数
from 科目成绩表
group by 科目) as t
order by 科目;

图片

  • 第1行表示数学科目的中位数位置范围为[2,2],也就是2。因为数学科目总共3个人,是奇数,所以中位数位置为2。
  • 第2行表示语文科目的中位数位置范围为[2,3]。因为语文科目总共4个人,是偶数,所以要知道中位数,需要知道2个位置的数字,而因为只有4个人,所以中位数位置为[2,3]。

猜你喜欢

转载自blog.csdn.net/godlovedaniel/article/details/111922733