hive sql系列(一)——找出所有科目成绩都大于某一学科平均成绩的学生

每天分享一个sql,帮助大家找到sql的快乐


需求:找出所有科目成绩都大于某一学科平均成绩的学生

建表语句

create table score(
    uid string,
    subject_id string,
    score int
)
row format delimited fields terminated by '\t'
;

数据

insert overwrite table score values
("1001","01",100),
("1001","02",100),
("1001","03",100),
("1002","01",90),
("1002","02",70),
("1002","03",50),
("1003","01",80),
("1003","02",60),
("1003","03",40);

实现

select
    t2.uid
from(
    select
        t1.uid,
        t1.subject_id,
        t1.score,
        t1.avg_score,
        if(t1.score > t1.avg_score,0,1) as flag --每科成绩大于某科平均分
    from(
        select
            uid,
            subject_id,
            score,
            cast(avg(score) over(partition by subject_id) as int) as avg_score
        from
            score
        )t1
    )t2
group by t2.uid
having sum(t2.flag)=0;

结果

t2.uid
1001
Time taken: 33.267 seconds, Fetched: 1 row(s)

分析

1、重点是对科目开窗求每个平均分,这样每个科目后面都会匹配对应的平均分
2、每一条数据都有学生每科的成绩和这个科目的平均分,可以直接判断科目成绩是否大于科目平均分
3、核心逻辑是flag处理,学生每科成绩大于所有科目的平均分,对于每个学生来说,只有一种情况,全部为0,
而每科成绩小于一科平均分便为1,这是一种反向思维
4、然后对flag求和,和为0就是符合要求的结果

扩展

select
    uid,
    subject_id,
    score,
    round(avg(score) over(partition by subject_id),2) as avg_score
from
    score
;
uid	subject_id	score	avg_score
1003	01	80	90.0
1002	01	90	90.0
1001	01	100	90.0
1003	02	60	76.67
1002	02	70	76.67
1001	02	100	76.67
1003	03	40	63.33
1002	03	50	63.33
1001	03	100	63.33
Time taken: 14.056 seconds, Fetched: 9 row(s)


开窗的结果会根据分区键进行匹配,也就是说在原有的行记录再添加一列,
这个列的每一行的值是开窗结果集,结果集的在每一行的值是与分区键匹配
用程序语言表述一下:
rows[keys:values] -- 多个不同的key对应多个相同或不同的values
over(partition by key) --开窗是以key作为分区键来读取数据
key:values --分区之后,原有数据变成多个子集:一个key对应多个values
avg() over(partition by key)--对每个结果集进行运算
key:result -- 运算之后,一个key对应一个result
rows[keys:results] --最终展示的结果是在原有的数据不变+新增一列result

select
    subject_id,
    round(avg(score),2)
from
    score
group by subject_id
;
subject_id	_c1
01	90.0
02	76.67
03	63.33
Time taken: 24.313 seconds, Fetched: 3 row(s)

分组统计会根据分组键进行分组,找到分组键列和聚合函数作用的列,相当于从原始数据集中
取出两列,行数不变
【扩展】where条件会减少行数
然后根据分组键切分成多个数据集,每个数据集数据类型相同,然后使用聚合函数计算,返回结果
再与分组键组成kv结构,就是最终看到的效果
用程序语言表述一下:
rows[rows:cols] -- 原始数据集,多行多列
group by key -- 指定分组键,
select col1,col2 -- 取出多列,数据变成多行少列
group by key & select col1,聚合函数(key)-- 这里会忽略聚合函数作用列,比较select中的key是否是group by中的key的子集
avg(key) --对每个子集的数据计算,返回结果
key:result -- 运算之后,一个key对应一个result,这就是最终结果

对比:
1、over(partition by)和group by的效果都是分组统计
2、over是原始数据不变,新增一列,group by是从原始数据集中选出子集,只能看到结果,没有原始数据信息
3、over(partition by)效果=原始数据集 join group by原始数据集

  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗少说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值