hive窗口函数入门
窗口函数over简介
先来看一下这个需求:求每个部门的员工信息以及部门的平均工资。在mysql中如何实现呢
SELECT emp.*, avg_sal
FROM empJOIN (SELECT deptno, round(AVG(ifnull(sal, 0))) AS avg_salFROM empGROUP BY deptno) tON emp.deptno = t.deptno
ORDER BY deptno;select emp.*,(select avg(ifnull(sal,0)) from emp B where B.deptno = A.deptno )
from emp A;
通过这个需求我们可以看到,如果要查询详细记录和聚合数据,必须要经过**两次查询*
*,比较麻烦。
这个时候,我们使用窗口函数,会方便很多。那么窗口函数是什么呢?
特点
-1) 窗口函数又名开窗函数
,属于分析函数的一种。
-2) 是一种用于解决复杂报表
统计需求的函数。
-3) 窗口函数常用于计算基于组
的某种值,它和聚合函数的不同之处是:对于每个组返回多行
,而聚合函数对于每个组只返回一行。
简单的说窗口函数对每条详细记录开一个窗口,进行聚合统计的查询
-4) 开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化。
-5) 窗口函数一般不单独使用
-6) 窗口函数内也可以分组和排序
参考下图:
**注意:**默认mysql老版本没有支持,在最新的8.0版本中支持, Oracle和Hive中都支持窗口函数
基本案例演示
数据准备(order.txt)
姓名 购买日期购买数量
saml 2018-01-01 10
saml 2018-01-08 55
tony 2018-01-07 50
saml 2018-01-05 46
tony 2018-01-04 29
tony 2018-01-02 15
saml 2018-02-03 23
mart 2018-04-13 94
saml 2018-04-06 42
mart 2018-04-11 75
mart 2018-04-09 68
mart 2018-04-08 62
neil 2018-05-10 12
neil 2018-06-12 80
drop table t_order;
--1. 创建order表:
create table if not exists t_order
(name string,orderdate string,cost int
) row format delimited fields terminated by '\t';
--2. 加载数据:
load data local inpath "/data/order.txt" into table t_order;
select * from t_order;
需求:查询每个订单的信息,以及订单的总数
– 1.不使用窗口函数
-- 查询所有明细
select * from t_order;
# 查询总量
select count(*) from t_order;
– 2.使用窗口函数:通常格式为 可用函数+over()函数
select *, count(*) over() from t_order;
+----+----------+----+--+
|name|orderdate |cost|c1|
+----+----------+----+--+
| |NULL |NULL|15|
|neil|2018-06-12|80 |15|
|neil|2018-05-10|12 |15|
|mart|2018-04-08|62 |15|
|mart|2018-04-09|68 |15|
|mart|2018-04-11|75 |15|
|saml|2018-04-06|42 |15|
|mart|2018-04-13|94 |15|
|saml|2018-02-03|23 |15|
|tony|2018-01-02|15 |15|
|tony|2018-01-04|29 |15|
|saml|2018-01-05|46 |15|
|tony|2018-01-07|50 |15|
|saml|2018-01-08|55 |15|
|saml|2018-01-01|10 |15|
+----+----------+----+--+
注意:
窗口函数是针对每一行数据的.
如果over中没有指定参数,默认窗口大小为全部结果集
需求:查询在2018年1月份购买过的顾客购买明细及总人数
select *,count(*) over() from t_order
where substring(orderdate,1,7)='2018-01'
+----+----------+----+--+
|name|orderdate |cost|c1|
+----+----------+----+--+
|tony|2018-01-02|15 |6 |
|tony|2018-01-04|29 |6 |
|saml|2018-01-05|46 |6 |
|tony|2018-01-07|50 |6 |
|saml|2018-01-08|55 |6 |
|saml|2018-01-01|10 |6 |
+----+----------+----+--+
distribute by子句
在over窗口中进行分组,对某一字段进行分组统计,窗口大小就是同一个组的所有记录
语法:
over(distribute by colname[,colname.....])
需求:查看顾客的购买明细及月购买总额
select *,sum(cost) over(distribute by month(orderdate)) sum
from t_order;+----+----------+----+----+
|name|orderdate |cost|sum |
+----+----------+----+----+
| |NULL |NULL|NULL|
|saml|2018-01-01|10 |205 |
|tony|2018-01-02|15 |205 |
|tony|2018-01-04|29 |205 |
|saml|2018-01-05|46 |205 |
|tony|2018-01-07|50 |205 |
|saml|2018-01-08|55 |205 |
|saml|2018-02-03|23 |23 |
|mart|2018-04-13|94 |341 |
|mart|2018-04-08|62 |341 |
|mart|2018-04-09|68 |341 |
|mart|2018-04-11|75 |341 |
|saml|2018-04-06|42 |341 |
|neil|2018-05-10|12 |12 |
|neil|2018-06-12|80 |80 |
+----+----------+----+----+
需求:查看顾客的购买明细及每个顾客的月购买总额
select *,sum(cost) over(distribute by month(orderdate),name)
from t_order;
+----+----------+----+----+
|name|orderdate |cost|c1 |
+----+----------+----+----+
| |NULL |NULL|NULL|
|saml|2018-01-01|10 |111 |
|saml|2018-01-05|46 |111 |
|saml|2018-01-08|55 |111 |
|tony|2018-01-02|15 |94 |
|tony|2018-01-04|29 |94 |
|tony|2018-01-07|50 |94 |
|saml|2018-02-03|23 |23 |
|mart|2018-04-09|68 |299 |
|mart|2018-04-11|75 |299 |
|mart|2018-04-13|94 |299 |
|mart|2018-04-08|62 |299 |
|saml|2018-04-06|42 |42 |
|neil|2018-05-10|12 |12 |
|neil|2018-06-12|80 |80 |
+----+----------+----+----+
sort by子句
sort by子句会让输入的数据强制排序 (强调:当使用排序时,窗口会在组内逐行变大)
语法: over([distribute by colname] [sort by colname [desc|asc]])
需求:查看顾客的购买明细及每个顾客的月购买总额,并且按照日期降序排序
select *, sum(cost) over (distribute by month(orderdate),name sort by orderdate desc)
from t_order;
+----+----------+----+----+
|name|orderdate |cost|c1 |
+----+----------+----+----+
| |NULL |NULL|NULL|
|saml|2018-01-08|55 |55 |
|saml|2018-01-05|46 |101 |
|saml|2018-01-01|10 |111 |
|tony|2018-01-07|50 |50 |
|tony|2018-01-04|29 |79 |
|tony|2018-01-02|15 |94 |
|saml|2018-02-03|23 |23 |
|mart|2018-04-13|94 |94 |
|mart|2018-04-11|75 |169 |
|mart|2018-04-09|68 |237 |
|mart|2018-04-08|62 |299 |
|saml|2018-04-06|42 |42 |
|neil|2018-05-10|12 |12 |
|neil|2018-06-12|80 |80 |
+----+----------+----+----+
注意:可以使用partition by + order by
组合来代替distribute by+sort by
组合
select name, orderdate, cost,
sum(cost) over (partition by name, month(orderdate) order by orderdate desc)
from t_order;
注意:也可以在窗口函数中,只写排序
,窗口大小
是全表记录。
实际上就是把整个表当作一个组了. 也是有这个需求的,毕竟不开窗不能看明细,然而又想当成一个组
select *, sum(cost) over (order by orderdate desc)
from t_order;+----+----------+----+---+
|name|orderdate |cost|c1 |
+----+----------+----+---+
|neil|2018-06-12|80 |80 |
|neil|2018-05-10|12 |92 |
|mart|2018-04-13|94 |186|
|mart|2018-04-11|75 |261|
|mart|2018-04-09|68 |329|
|mart|2018-04-08|62 |391|
|saml|2018-04-06|42 |433|
|saml|2018-02-03|23 |456|
|saml|2018-01-08|55 |511|
|tony|2018-01-07|50 |561|
|saml|2018-01-05|46 |607|
|tony|2018-01-04|29 |636|
|tony|2018-01-02|15 |651|
|saml|2018-01-01|10 |661|
| |NULL |NULL|661|
+----+----------+----+---+
Window子句
如果要对窗口的结果做更细粒度的划分,那么就使用window
子句,常见的有下面几个
PRECEDING:往前
FOLLOWING:往后
CURRENT ROW:当前行
UNBOUNDED:起点,
UNBOUNDED PRECEDING:表示从前面的起点,
UNBOUNDED FOLLOWING:表示到后面的终点
一般window子句都是rows开头
案例:
select name,orderdate,cost,sum(cost) over () as sample1,--所有行相加sum(cost) over (partition by name) as sample2,-- 按name分组,组内数据相加sum(cost) over (partition by name order by orderdate) as sample3,-- 按name分组,组内数据累加sum(cost)over (partition by name order by orderdate rows between UNBOUNDED PRECEDING and current row ) as sample4,-- 与sample3一样,由起点到当前行的聚合sum(cost)over (partition by name order by orderdate rows between 1 PRECEDING and current row) as sample5, -- 当前行和前面一行做聚合sum(cost)over (partition by name order by orderdate rows between 1 PRECEDING AND 1 FOLLOWING ) as sample6,-- 当前行和前边一行及后面一行sum(cost)over (partition by name order by orderdate rows between current row and UNBOUNDED FOLLOWING ) as sample7 -- 当前行及后面所有行from t_order;
+----+----------+----+-------+-------+-------+-------+-------+-------+-------+
|name|orderdate |cost|sample1|sample2|sample3|sample4|sample5|sample6|sample7|
+----+----------+----+-------+-------+-------+-------+-------+-------+-------+
| |NULL |NULL|661 |NULL |NULL |NULL |NULL |NULL |NULL |
|mart|2018-04-08|62 |661 |299 |62 |62 |62 |130 |299 |
|mart|2018-04-09|68 |661 |299 |130 |130 |130 |205 |237 |
|mart|2018-04-11|75 |661 |299 |205 |205 |143 |237 |169 |
|mart|2018-04-13|94 |661 |299 |299 |299 |169 |169 |94 |
|neil|2018-05-10|12 |661 |92 |12 |12 |12 |92 |92 |
|neil|2018-06-12|80 |661 |92 |92 |92 |92 |92 |80 |
|saml|2018-01-01|10 |661 |176 |10 |10 |10 |56 |176 |
|saml|2018-01-05|46 |661 |176 |56 |56 |56 |111 |166 |
|saml|2018-01-08|55 |661 |176 |111 |111 |101 |124 |120 |
|saml|2018-02-03|23 |661 |176 |134 |134 |78 |120 |65 |
|saml|2018-04-06|42 |661 |176 |176 |176 |65 |65 |42 |
|tony|2018-01-02|15 |661 |94 |15 |15 |15 |44 |94 |
|tony|2018-01-04|29 |661 |94 |44 |44 |44 |94 |79 |
|tony|2018-01-07|50 |661 |94 |94 |94 |79 |79 |50 |
+----+----------+----+-------+-------+-------+-------+-------+-------+-------+
需求:查看顾客到目前为止的购买总额
select name,orderdate,cost,sum(cost)over (partition by name order by orderdate rows between unbounded preceding and current row ) as allCount
from t_order;
+----+----------+----+--------+
|name|orderdate |cost|allcount|
+----+----------+----+--------+
| |NULL |NULL|NULL |
|mart|2018-04-08|62 |62 |
|mart|2018-04-09|68 |130 |
|mart|2018-04-11|75 |205 |
|mart|2018-04-13|94 |299 |
|neil|2018-05-10|12 |12 |
|neil|2018-06-12|80 |92 |
|saml|2018-01-01|10 |10 |
|saml|2018-01-05|46 |56 |
|saml|2018-01-08|55 |111 |
|saml|2018-02-03|23 |134 |
|saml|2018-04-06|42 |176 |
|tony|2018-01-02|15 |15 |
|tony|2018-01-04|29 |44 |
|tony|2018-01-07|50 |94 |
+----+----------+----+--------+
需求:求每个顾客最近三次的消费总额
select name,orderdate,cost,sum(cost)over (partition by name order by orderdate rows between 2 preceding and current row ) as allCount
from t_order;
+----+----------+----+--------+
|name|orderdate |cost|allcount|
+----+----------+----+--------+
| |NULL |NULL|NULL |
|mart|2018-04-08|62 |62 |
|mart|2018-04-09|68 |130 |
|mart|2018-04-11|75 |205 |
|mart|2018-04-13|94 |237 |
|neil|2018-05-10|12 |12 |
|neil|2018-06-12|80 |92 |
|saml|2018-01-01|10 |10 |
|saml|2018-01-05|46 |56 |
|saml|2018-01-08|55 |111 |
|saml|2018-02-03|23 |124 |
|saml|2018-04-06|42 |120 |
|tony|2018-01-02|15 |15 |
|tony|2018-01-04|29 |44 |
|tony|2018-01-07|50 |94 |
+----+----------+----+--------+
总结
- 窗口函数的意义在于
明细+聚合
,二者缺一不可 - 理解分组的大小雨窗口大小的关系
- window子句是比Partition by更细粒度的统计
- 如果既要
明细又要聚合
,就要用到开窗函数
hive窗口函数入门相关推荐
- Hive窗口函数小结
文章目录 一.窗口函数作用 1.1.测试数据 1.2.应用场景 二.窗口函数概念 2.1.语法结构 2.2.分析函数 2.3.over函数的参数 三.窗口函数入门 3.1.over(partition ...
- 大数据技术-hive窗口函数详解
有不少同学一听这个标题,hive窗口函数是什么鬼?没听说过还有窗口函数这个东西啊,其实它的用处可大了,下面听小千慢慢道来. hive窗口函数 窗口函数指定了函数工作的数据窗口大小(当前行的上下多少行) ...
- mysql窗口函数_MySQL8.0窗口函数入门实践及总结
前言 MySQL8.0之前,做数据排名统计等相当痛苦,因为没有像Oracle.SQL SERVER .PostgreSQL等其他数据库那样的窗口函数.但随着MySQL8.0中新增了窗口函数之后,针对这 ...
- hadoop hive hbase 入门学习 (二)
hadoop 自学系列 hadoop hive hbase 入门学习 (一) hadoop安装.hdfs学习及mapreduce学习 hadoop 软件下载 (hadoo ...
- HiveQL学习笔记(四):Hive窗口函数
本系列是本人对Hive的学习进行一个整理,主要包括以下内容: 1.HiveQL学习笔记(一):Hive安装及Hadoop,Hive原理简介 2.HiveQL学习笔记(二):Hive基础语法与常用函数 ...
- hive窗口函数使用
hive窗口函数的使用 前言 一.hive窗口函数语法 1.over()窗口函数的语法结构 1.1.over()函数中的三个函数讲解 2.常与over()一起使用的分析函数 2.1.聚合类 2.2.排 ...
- Hive从入门到放弃——HiveQL表级别DDL设计的艺术性(五)
HiveQL数据库中的表DDL操作 博客Hive从入门到放弃--HiveQL数据库级别DDL设计的艺术性(四)聊完了数据库的基本操作,我们再来聊聊Hive内表的操作. 创建表 官方推荐建表的结 ...
- Hive 窗口函数 实现原理
Hive 窗口函数 实现原理 hive中窗口函数的实现,主要是借助于一个叫做 Windowing Table Function 的Partitioned Table Function Partitio ...
- hive 窗口函数(持续更新)
hive窗口函数语法 avg().sum().max().min()等是分析函数,而over()才是窗口函数,下面我们来看看over()窗口函数的语法结构.及常与over()一起使用的分析函数: 1. ...
最新文章
- php大号字体代码,支持中文字母数字、自定义字体php验证码代码
- tp5 上传文件乱码问题
- JavaEE Tutorials (17) - Java消息服务示例
- Java EE 7中的WebSocket客户端API
- Pytorch 加载部分预训练模型并冻结某些层
- oracle事务提交前更新机制,Oracle 事务机制 批量添加,修改,更新
- 如何才能做到网站高并发访问?
- 失业几个月找不到工作是一种怎样的体验?
- 新增了归并数组的方法!
- 多校3 1008 Solve this interesting problem
- 010 Editor v8.0.1(32 - bit) 算法逆向分析、注册机编写
- mugen linux主程序,mugen主程序win版下载
- bp神经网络优化算法对比,bp神经网络的优化算法
- ABBYY FineReader OCR图片文字识别软件安装应用
- 冒犯有时是必要的:如何开启一段亲密关系?
- 【kubernetes】k8s的job和cronjob详细说明【job、cronjob(cj)、descheduler(pod均衡)】
- worldpress 添加网站关键词和描述
- 计算机毕业设计Java-ssmC语言教学辅导网站源码+系统+数据库+lw文档
- 商业图表案例3-CO2排放量与人均GDP
- 治疗脚气、脚臭偏方!
热门文章
- tensorflow2.0 图像处理项目_UCOSIII移植——STM32F769I 图像处理能力评测之五
- 一加6屏幕测试代码_一加 7的普通版与Pro/参数对比
- linux shell 后台执行脚本的方法 脚本后台运行 后台运行程
- Eclipse中查看JDK类库的源代码
- HTML表单效果图,html-图片/表格/表单
- Vue 动画 过渡的类名
- oracle sql 导入mysql数据库备份_使用PL/SQL连接oracle数据库,并将数据进行导出备份和导入恢复...
- css手型指针_前端基础面试题(HTML+CSS部分)
- linux unix域socket_从文件描述符到Socket
- linux 22 口令自动传马,近期用到的linux命令