Hive中的开窗操作over()

前提


over() 可以为 聚合函数,窗口函数和分析函数进行开窗操作;
开窗之后,每一行的数据都会对应一个数据窗口,这个数据窗口中的数据可能会随着行的变化而变化。

over(参数) 中可以指定的参数

over() 开窗开出来的数据是整个查询结果排除开窗操作,都执行完之后的数据。也可以说是开窗操作是在整个select查询结束后才执行的,因此开窗出来的数据也是在当前select的查询结果上进行划分的。

over中可以指定的参数(官方定义: WINDOW specification):

(ROWS | RANGE) BETWEEN (UNBOUNDED | [num]) PRECEDING AND ([num] PRECEDING | CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING)
(ROWS | RANGE) BETWEEN CURRENT ROW AND (CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING)
(ROWS | RANGE) BETWEEN [num] FOLLOWING AND (UNBOUNDED | [num]) FOLLOWING
rows 限定的是行所在的范围,range限定的是某一列的值所在的范围

  • partition by col:按照col进行分区(类似于分组),每个分区拥有自己独立的数据窗口
  • order by col:窗口中的数据按照col进行排序;
  • current row :当前行
  • n preceding:往前n行数据
  • n following:往后n行数据
  • unbounded:有两种边界值:unbounded preceding 表示所开窗出来的起始数据(最小值);unbounded following 表示所开窗出来的最后一行数据(最大值)。

两个常用的窗口函数,配合over开窗来使用

  1. lag(col, n) 获取当前行往前第n行col列的数据,也可以指定默认值。
  2. lead(col, n) 获取当前行往后第n行col列的数据。

常用的分析函数

  1. RANK 排名,排序相同时会重复,总数不变:1,1,3,4
  2. ROW_NUMBER 根据顺序计算,相同元素的排名不会重复 :1,2,3,4
  3. DENSE_RANK (稠密的排名) 相同元素的排名会重复,但是总数会减少:1,1,2,3
  4. NTILE(n), 为开窗出来的每行数据进行分组编号, n为指定的分组个数,返回每行数据的分组编号。当数据不能均匀分布时,默认从第一个组开始一次增加一个元素,不同组别之间的元素的个数最多相差一个元素

接下来我们通过例子,更加直观的学习上述所述的开窗相关的内容。

数据准备


name	orderdate	cost
------------------------
jack	2017-01-01	10
tony	2017-01-02	15
jack	2017-02-03	23
tony	2017-01-04	29
jack	2017-01-05	46
jack	2017-04-06	42
tony	2017-01-07	50
jack	2017-01-08	55
mart	2017-04-08	62
mart	2017-04-09	68
neil	2017-05-10	12
mart	2017-04-11	75
neil	2017-06-12	80
mart	2017-04-13	94

创建表并加载数据

create table business(
name string, 
orderdate string,
cost int
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

load data local inpath "/opt/module/datas/business.txt" into table business;

查询表中的所有元素

business.name	business.orderdate	business.cost
jack	2017-01-01	10
tony	2017-01-02	15
jack	2017-02-03	23
tony	2017-01-04	29
jack	2017-01-05	46
jack	2017-04-06	42
tony	2017-01-07	50
jack	2017-01-08	55
mart	2017-04-08	62
mart	2017-04-09	68
neil	2017-05-10	12
mart	2017-04-11	75
neil	2017-06-12	80
mart	2017-04-13	94

查询在2017年4月份购买过的顾客及总人数(over() 简单的使用)

select
	name,
	count(*) over()
from business
where substring(orderdate, 1, 7)='2017-04'
group by name;

结果:
+----+------------------------------------------------------------------------+
|name|count(1) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)|
+----+------------------------------------------------------------------------+
|mart|2                                                                       |
|jack|2                                                                       |
+----+------------------------------------------------------------------------+

上述代码我们通过spark on hive的方式来访问hive中的数据,加快执行效率;如果没有spark,可以之间在hive shell中运行hql语句

partition by col测试:查询顾客的购买明细及月购买总额

    val spark: SparkSession = SparkSession.builder()
      .appName("HiveRead").master("local[*]")
      .enableHiveSupport()
      .config("spark.sql.warehouse.dir", "hdfs://hadoop102:9000/user/hive/warehouse")
      .getOrCreate()
    spark.sql(
      """
        |select
        | name,
        | orderdate,
        | cost,
        | sum(cost) over(partition by month(orderdate))
        |from business
        |""".stripMargin
    ).show(false)

结果:
+----+----------+----+-------------------------------------------------------------------------------------------------------------------------------------+
|name|orderdate |cost|sum(CAST(cost AS BIGINT)) OVER (PARTITION BY month(CAST(orderdate AS DATE)) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)|
+----+----------+----+-------------------------------------------------------------------------------------------------------------------------------------+
|jack|2017-01-01|10  |205                                                                                                                                  |
|tony|2017-01-02|15  |205                                                                                                                                  |
|tony|2017-01-04|29  |205                                                                                                                                  |
|jack|2017-01-05|46  |205                                                                                                                                  |
|tony|2017-01-07|50  |205                                                                                                                                  |
|jack|2017-01-08|55  |205                                                                                                                                  |
|neil|2017-06-12|80  |80                                                                                                                                   |
|neil|2017-05-10|12  |12                                                                                                                                   |
|jack|2017-04-06|42  |341                                                                                                                                  |
|mart|2017-04-08|62  |341                                                                                                                                  |
|mart|2017-04-09|68  |341                                                                                                                                  |
|mart|2017-04-11|75  |341                                               
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值