hive关于窗口函数的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hive关于窗口函数的使用相关的知识,希望对你有一定的参考价值。

参考技术A 窗口函数可以理解为给数据划到一个窗口内并排上序号。

over()即那个窗口函数,需要搭配其他函数进行分析

over()括号内部可以加上partiton by进行分组,加上order by进行排序。不加上partition by是对所有数据开了一个窗,加上partition by是对分组内部所有数据进行开窗。加上order by对分组内数据按排序进行开窗。

形如over(partition by class order by score),这个会对class字段进行分组,然后在分组的内部基于score进行排序。

此外还可以给窗口计算加行范围,over(rows between 开始位置 and 结束位置),开始位置和结束位置可以填的包括
PRECEDING:往前
FOLLOWING:往后
CURRENT ROW:当前行
UNBOUNDED PRECEDING:窗口的起点
UNBOUNDED FOLLOWING:窗口的终点
形如:over(partition by class order by score rows between UNBOUNDED PRECEDING and 1 PRECEDING),这个会对class字段进行分组,然后在排序后从窗口第一个值取到当前行前一个值

先假设一个总分表score_table有姓名name、班级class、总分score三个字段

row_number()、rank()、dense_rank()
对各个班级内部进行总分排名
对排名连续无相同名次,比如有三个分数98、98、97,排名为1、2、3,使用row_number()
形如sql:
select *, row_number() over(partition by class order by score desc) as num from score_table;
对排名不连续有相同名次,比如有三个分数98、98、97,排名为1、1、3,使用rank()
形如sql:
select *, rank() over(partition by class order by score desc) as num from score_table;
对排名连续有相同名次,比如有三个分数98、98、97,排名为1、1、2使用dense_rank()
形如sql:
select *,dense_rank() over(partition by class order by score desc) as num from score_table;

avg(列名)、sum(列名)、max(列名)、min(列名)
计算排挤内前各个名次的平均分
形如sql:
select *, avg(score) over(partition by class order by score desc) as num from score_table;

ntile(n)函数
把窗口内按班级分组后的数据按先成绩排名后分成3份,分成1、2、3组
形如sql:
select *, ntile(3) over(partition by class order by score desc) as num from score_table;

lag(列名,往前的行,默认值)
把窗口内按班级分组后的数据,取该分组内每一行数据的前一名同学的成绩,如果第一名就显示100;
形如sql:
select *, lag(score,1,100) over(partition by class order by score desc) as num from score_table;

lead(列名,往后的行,默认值)
把窗口内按班级分组后的数据,取该分组内每一行数据的后一名同学的成绩,如果最后一名就显示0;
形如sql:
select *, lag(score,1,0) over(partition by class order by score desc) as num from score_table;

first_value(列名)和last_value(列名)
把窗口内按班级分组后的数据,取该分组内第一名同学的成绩
形如sql:select *, first_value(score) over(partition by class order by score desc) as num from score_table;
把窗口内按班级分组后的数据,取该分组内最后一名同学的成绩
形如sql:select *, last_value(score) over(partition by class order by score desc) as num from score_table;

总结:
窗口函数的使用大致遵循以下
函数名字(arg1, arg2, ... argN) OVER( [PARTITION BY 分组列] [ORDER BY 排序列] [计算的行范围] )
本文举的函数有row_number()、rank()、dense_rank()、avg(列名)、sum(列名)、max(列名)、min(列名)、ntile(n)、lag(列名,往前的行,默认值)、lead(列名,往后的行,默认值)、first_value(列名)和last_value(列名)

MySQL/ Hive:使用窗口或分析函数连接条件行

【中文标题】MySQL/ Hive:使用窗口或分析函数连接条件行【英文标题】:MySQL/ Hive : Join conditioned rows using windowing or analytical functions 【发布时间】:2016-10-19 06:40:48 【问题描述】:

我有两个表,我想用特定的逻辑加入它们。

Table_1 (S_No, ID, Date1, Date2)

S_No    ID  Date1   Date2
1   id1 2014-05-01  2014-07-03
2   id1 2015-03-23  2016-06-18
3   id1 2016-06-21  2016-07-29

表_2(S_No_New、ID_New、Date_New)

S_No_New    ID_New  Date_New
2_1 id1 2014-04-25
2_2 id1 2014-06-14
2_3 id1 2015-01-10
2_4 id1 2015-02-15
2_5 id1 2015-05-17
2_6 id1 2016-04-24
2_7 id1 2016-06-19
2_8 id1 2016-06-25
2_9 id1 2016-07-11
2_10    id1 2016-08-11
2_11    id1 2016-08-16

我想以这样的方式加入上面的两个表,以便我计算在 Date1 之前以及 Date1 和 Date2 之间 table_2 中有多少行,然后当我们移动到下一行时,我们必须使用数据到目前为止,还没有计算相同的 ID。

如果我们在表 1 中最后一个 Date2 条目之后在 table_2 中有一个日期条目,那么我们需要在 S_No 和类似的剩余列详细信息中添加一个新行,并添加“+1”。

总的来说,这个问题可以分为两部分: 1) 获取计数列 2) 将多余的行加起来(本例中为 S_No "4")

如果您知道两者中的任何一个的解决方案,请放弃答案。

最终输出:

S_No    ID  Date1   Date2   Count_pre   Count_Between
1   id1 2014-05-01  2014-07-03  1   1
2   id1 2015-03-23  2016-06-18  2   2
3   id1 2016-06-21  2016-07-29  1   2
4   id1 NULL    NULL    2   0

逻辑: S_No 1 : Count_Pre = 2014-05-01 之前的日期 Count_between = 2014-05-01 和 2014-07-03 之间的日期

S_No 2 : Count_Pre = 2014-07-03 和 2015-03-23 之间的日期 Count_between = 2015-03-23 和 2016-06-18 之间的日期 等等

中间表必须如下所示:

S_No    ID  Date    Date2   S_No_New    Date_New
1   id1 2014-05-01  2014-07-03  2_1 2014-04-25
1   id1 2014-05-01  2014-07-03  2_2 2014-06-14
2   id1 2015-03-23  2016-06-18  2_3 2015-01-10
2   id1 2015-03-23  2016-06-18  2_4 2015-02-15
2   id1 2015-03-23  2016-06-18  2_5 2015-05-17
2   id1 2015-03-23  2016-06-18  2_6 2016-04-24
3   id1 2016-06-21  2016-07-29  2_7 2016-06-19
3   id1 2016-06-21  2016-07-29  2_8 2016-06-25
3   id1 2016-06-21  2016-07-29  2_9 2016-07-11
4   id1 NULL    NULL    2_10    2016-08-11
4   id1 NULL    NULL    2_11    2016-08-16

我尝试了不同的窗口和分析功能,但无法解决这个问题。 是否可以在 hive(基本 sql)中进行这种连接?

注意:编辑 2:我需要在 hive 中实现它,它支持所有内置函数,但不支持 mysql 中的变量。它支持聚合、窗口化和分析功能。

编辑:将日期格式从 dd/mm/yyyy 更改为 yyyy-mm-dd

【问题讨论】:

mysql 还是 sql-server? 它实际上是 MySQL。 1.将日期存储为日期 您可以根据需要修改或强制转换列。您能否提供有关您的评论的更多详细信息。 所以 date_new = 2014-06-14 对于 S_no = 1 应计为 count_between 一次,但对于 s_no = 2 不计为 count_pre? 【参考方案1】:
    SELECT t.t1s_no,t.date1,t.date2,
         sum(case when t.srce = 'P' then 1 else 0 end) as 'prev',
         sum(case when t.srce = 'B' then 1 else 0 end) as 'between',
         sum(case when t.srce = 'X' then 1 else 0 end) as 'missing'
FROM 
(
SELECT S.*,
        ROW_NUMBER() OVER (PARTITION BY S.DATE_NEW ORDER BY s.srce ,S.DATE1) RN
FROM
(SELECT 'P' AS SRCE,T1.S_NO T1S_NO,T1.ID T1ID,T1.DATE1 DATE1,T1.DATE2 DATE2,T2.DATE_NEW
FROM    TABLE_1 T1
JOIN    TABLE_2 T2 ON T2.DATE_NEW < T1.DATE1
UNION 
SELECT 'B' AS SRCE,T1.S_NO T1S_NO,T1.ID T1ID,T1.DATE1 DATE1,T1.DATE2 DATE2,T2.DATE_NEW
FROM    TABLE_1 T1
JOIN    TABLE_2 T2 ON T2.DATE_NEW BETWEEN T1.DATE1 AND T1.DATE2
UNION 
SELECT 'X' AS SRCE,4 T1S_NO,T1.ID T1ID,T1.DATE1 DATE1,T1.DATE2 DATE2,T2.DATE_NEW
FROM    TABLE_2 T2
left JOIN   TABLE_1 T1 ON (T2.DATE_NEW BETWEEN T1.DATE1 AND T1.DATE2) or (t2.date_new < t1.date1) 
where   t1.date1 is null
) S 
) T
WHERE T.RN = 1 
group   by t.t1s_no,t.date1,t.date2
ORDER BY T.T1S_NO, T.DATE1
;

结果

t1s_no      date1            date2            prev        between     missing
----------- ---------------- ---------------- ----------- ----------- -----------
          1       2014-05-01       2014-07-03           1           1           0
          2       2015-03-23       2016-06-18           2           2           0
          3       2016-06-21       2016-07-29           1           2           0
          4             NULL             NULL           0           0           2

(4 rows affected)

【讨论】:

对于 S_No = 2 它实际上应该是每个 2。已更新有问题。我想在 hive 中使用它并且它不支持变量,是否可以在不使用变量的情况下执行此操作。请阅读编辑以获取更多更新 对不起,我对更新不好。应该早点把它放在 hive 实现上。 我不知道 hive,但它似乎有一个 row_number() 函数,它可能等同于我使用的变量方法。如果 hive row_number() 函数看起来像这个 row_number() over (partition by ... order by ...) 那么我可以使用 t-sql 更新我的答案。如果您希望我这样做,请告诉我。 是的,hive 支持 row_number() 函数,如 row_number() over (partition by ... order by ...)。如果您可以修改上述查询,那将非常有帮助。提前致谢。

以上是关于hive关于窗口函数的使用的主要内容,如果未能解决你的问题,请参考以下文章

Hive学习窗口函数源码阅读

数据仓库工具Hive——窗口函数,DML,事务

hive窗口函数及示例

hive窗口函数及示例

Hive sql及窗口函数

大数据技术-hive窗口函数详解