前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >hive sql(一)

hive sql(一)

作者头像
大数据最后一公里
发布2021-08-05 10:13:43
7580
发布2021-08-05 10:13:43
举报
文章被收录于专栏:大数据最后一公里
代码语言:javascript
复制
每天分享一个sql,帮助大家找到sql的快乐

需求

代码语言:javascript
复制
找出所有科目成绩都大于某一学科平均成绩的学生

建表语句

代码语言:javascript
复制
create table score(
    uid string,
    subject_id string,
    score int
)
row format delimited fields terminated by '\t'
;

数据

代码语言:javascript
复制
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);

实现

代码语言:javascript
复制
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)

分析

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

扩展

代码语言:javascript
复制
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原始数据集
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据最后一公里 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档