hive分析相关窗口函数三之取数相关

1、开窗函数取特定值
开窗函数中经常遇到去取出某个特定的值,具体的相关函数为
lag() : 与lead相反,用于统计窗口内往上第n行值。第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为NULL的时候,取默认值,如果不指定,则为NULL).
**lead(col,n,default)**与lag相反,统计分组内往下第n行值。第一个参数为列名,第二个参数为往下第n行(可选,不填默认为1),第三个参数为默认值(当往下第n行为NULL时候,取默认值,如不指定,则为NULL)。
**FIRST_VALUE()😗*取分组内排序后,截止到当前行,分组内第一个值。
**LAST_VALUE()😗*取分组内排序后,截止到当前行,最后一个值.

spark 3 新函数max_by
max_by(t.poi_name, t.update_time) over(partition by t.dt, t.poi_id) as poi_name,
意思是 通过t.dt 和t.poi_id 开窗后,取出update_time最大的poi_name.
注意:last_value 默认窗口是 rows between unbounded preceding and current row,表示当前永远是分组内最后一个值,需要手动改成成Rows between unbounded preceding and unbounded following.

1、开窗函数值具体例子
lag 实现分组内上一行的营业额,如果没有上一行则取个默认值(1)。
注意:lag 不支持 range between 1 preceding and current row
自己测试结果只支持 rows。


select  month,       
           shop,
           money,
           lag(money,1,1) over(partition by shop order by month) as before_money,
           form  temp_test12;
结果:
month  shop  money  before_money
2019-01  a  1  1
2019-02  a  2  1
2019-03  a  3  2
2019-04  a  4  3
2019-05  a  5  4
2019-06  a  6  5
2019-01  b  2  1
2019-02  b  4  2
2019-03  b  6  4
2019-04  b  8  6
2019-05  b  10  8
2019-06  b  12  10

lead()实现分组内下一个月营业额需求

   SELECT month
      ,shop
      ,MONEY
      ,LEAD(MONEY, 1, 7) OVER ( PARTITION BY shop ORDER BY month ) AS after_money
      ,LEAD(MONEY, 1) OVER (PARTITION BY shop ORDER BY month) AS after_money   --第三个参数不写的话,如果没有下一行值,默认取null
      ,LEAD(MONEY, 2, 7) OVER (PARTITION BY shop ORDER BY month) AS after_2month_money  --取两个月后的营业额
FROM temp_test12;


结果:
month  shop  money  after_money  after_money  after_2month_money
2019-01  a  1  2  2  3
2019-02  a  2  3  3  4
2019-03  a  3  4  4  5
2019-04  a  4  5  5  6
2019-05  a  5  6  6  7
2019-06  a  6  7  NULL  7
2019-01  b  2  4  4  6
2019-02  b  4  6  6  8
2019-03  b  6  8  8  10
2019-04  b  8  10  10  12
2019-05  b  10  12  12  7
2019-06  b  12  7  NULL  7
解释说明:
shop为a时,after_money指定了往下第1行的值,如果没有下一行值,默认取null,这里指定为1。
a的第1行,往下1行值为第2行营业额值,2。
a的第2行,往下1行值为第3行营业额值,4。
a的第6行,往下1行值为NULL,指定第三个参数取7,不指定取null。        

FIRST_VALUE()
select * ,first_value(s_id) over (partition by c_id order by s_score)first_show from score;
在这里插入图片描述
结果显示:也就是说,得到的结果是对应c_id的首个s_id的值。
LAST_VALUE()
select * ,last_value(s_id) over (partition by c_id order by s_score)last_show from score;
在这里插入图片描述
由结果看出:last_value() 默认的统计范围是 rows between unbounded preceding and current row ,也就是去当前行数据与当前之前的数据的比较。
那么,如何像**first_value()**那样直接在每行数据中显示最后的那个数据呢?
在order by 条件的后面加上语句:rows between unbounded preceding and unbounded following
即:

select * ,last_value(s_id) over(partition by c_id order by s_score rows between unbounded preceding and unbounded following ) last_show  from  score;

即结果达到预期,每一行结果直接返回分组内最后结果值了
在这里插入图片描述

备注:todo
range between 区别 raws 待整理。
1、 range between 1 preceding and current row
例子

select 
 dt,
 name,
 id,
 sum(id) over(partition by name order by    字段 asc range  between 1 preceding and current row) as before_id
from test1

其中 字段类型必须是数值类型。

### HIVE 窗口函数使用教程与示例 Hive窗口函数是一种强大的工具,允许在不减少原始结果集行的情况下执行复杂的数据操作。它通过`OVER()`子句定义了一个“窗口”,即一个数据子集,在这个子集中可以应用各种分析和聚合功能[^2]。 #### 基本语法 窗口函数的基本语法如下所示: ```sql Function(arg1,..., argn) OVER ( [PARTITION BY <...>] [ORDER BY <....>] [<window_expression>] ) ``` - `Function`: 可以是一个聚合函(如`SUM`, `MAX`, `AVG`)、排序函(如`RANK`, `ROW_NUMBER`),或者是其他类型的分析(如`LEAD`, `LAG`, `FIRST_VALUE`)。 - `PARTITION BY`: 定义如何将数据划分为多个分区或“窗口”。类似于SQL中的`GROUP BY`语句,但它不会减少行的量[^4]。 - `ORDER BY`: 指定每个分区内记录的排列顺序。支持升序(`ASC`)和降序(`DESC`)两种方式[^4]。 - `<window_expression>`: (可选)进一步控制窗口中哪些行会被考虑进去,默认情况下会包含整个窗口的所有行。 #### 实际案例解析 ##### 示例 1: 计算累积销售额 假设我们有一张交易表`trade`,其中包含了用户的每次交易金额以及日期信息。现在我们需要按用户ID来统计每一天之前的总销售量: ```sql SELECT user_id, trade_date, trade_num, SUM(trade_num) OVER(PARTITION BY user_id ORDER BY trade_date) AS cumulative_sales FROM trade; ``` 这里利用了`SUM()`作为窗口函数的一部分,并通过`PARTITION BY user_id`指定了按照不同用户划分窗口;同时借助`ORDER BY trade_date`实现了基于时间序列上的累加效果[^5]。 ##### 示例 2: 排名计算 如果我们想获每种商品类别中最畅销的产品排名,则可以用到`ROW_NUMBER()`这样的排序类窗口函数: ```sql SELECT product_category, product_name, sales_amount, ROW_NUMBER() OVER(PARTITION BY product_category ORDER BY sales_amount DESC) AS rank_within_category FROM productsales; ``` 此查询首先依据产品所属的大类进行分割(`PARTITION BY product_category`),接着再针对每一类产品内部根据销量大小做降序处理(`ORDER BY sales_amount DESC`),最后赋予相应位置编号给各个条目[^3]。 ##### 示例 3: 获前驱/后继值 有时候可能还需要访问当前行之前或者之后某一行的具体值,这时就可以采用像`LAG()` / `LEAD()`之类的特殊用途窗口函数实现这一目标。例如要查看前一天同一客户的消费额变化情况: ```sql SELECT user_id, transaction_date, amount_spent, LAG(amount_spent, 1) OVER(PARTITION BY user_id ORDER BY transaction_date) AS previous_day_spendings FROM transactions; ``` 在这里选择了`LAG()`函并设置偏移参为1表示紧邻前面那笔交易的结果。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值