精华内容
下载资源
问答
  • Hive窗口函数实例

    2021-05-21 19:39:25
    – 建表 CREATE DATABASE IF NOT EXISTS TEST; CREATE TABLE TEST.COSTITEM ( NAME STRING, ORDERDATE DATE, COST STRING); – 数据加载 INSERT INTO TEST.COSTITEM VALUES ('jack','2020-01-01','10');...

    – 建表

    CREATE DATABASE IF NOT EXISTS TEST;
    CREATE TABLE TEST.COSTITEM
    ( NAME STRING,
    ORDERDATE DATE,
    COST STRING);
    

    – 数据加载

    INSERT INTO  TEST.COSTITEM  VALUES ('jack','2020-01-01','10');
    INSERT INTO  TEST.COSTITEM  VALUES ('tony','2020-01-02','15');
    INSERT INTO  TEST.COSTITEM  VALUES ('jack','2020-02-03','23');
    INSERT INTO  TEST.COSTITEM  VALUES ('tony','2020-01-04','29');
    INSERT INTO  TEST.COSTITEM  VALUES ('jack','2020-01-05','46');
    INSERT INTO  TEST.COSTITEM  VALUES ('jack','2020-04-06','42');
    INSERT INTO  TEST.COSTITEM  VALUES ('tony','2020-01-07','50');
    INSERT INTO  TEST.COSTITEM  VALUES ('jack','2020-01-08','55');
    INSERT INTO  TEST.COSTITEM  VALUES ('mart','2020-04-08','62');
    INSERT INTO  TEST.COSTITEM  VALUES ('mart','2020-04-09','68');
    INSERT INTO  TEST.COSTITEM  VALUES ('neil','2020-05-10','12');
    INSERT INTO  TEST.COSTITEM  VALUES ('mart','2020-04-11','75');
    INSERT INTO  TEST.COSTITEM  VALUES ('neil','2020-06-12','80');
    INSERT INTO  TEST.COSTITEM  VALUES ('mart','2020-04-13','94');
    

    –查询结果:

    select * from costitem;
    

    在这里插入图片描述
    –SQL实现:

    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,   -- 组内由起点到当前行的聚合
    	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 
        TEST.COSTITEM;
    

    从上述结果看出:

    sample3 和 sample4实际是等效的,只是语法表达不同。
    sample2和sample3 语法表达有点像,实际上含义不同。
    
    展开全文
  • Hive 窗口函数

    2020-06-01 19:45:25
    Hive 窗口函数简介概念数据准备实例聚合函数+overpartition by子句order by子句window子句窗口函数中的序列函数NTILELAG和LEAD函数first_value和last_value扩展:总结: 简介 本文主要介绍hive中的窗口函数.hive中的...

    简介

    本文主要介绍hive中的窗口函数.hive中的窗口函数和sql中的窗口函数相类似,都是用来做一些数据分析类的工作,一般用于olap分析(在线分析处理)。

    概念

    我们都知道在sql中有一类函数叫做聚合函数,例如sum()、avg()、max()等等,这类函数可以将多行数据按照规则聚集为一行,一般来讲聚集后的行数是要少于聚集前的行数的.但是有时我们想要既显示聚集前的数据,又要显示聚集后的数据,这时我们便引入了窗口函数.

    在深入研究Over字句之前,一定要注意:在SQL处理中,窗口函数都是最后一步执行,而且仅位于Order by字句之前。

    数据准备

    我们准备一张order表,字段分别为name,orderdate,cost.数据内容如下:

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

    实例

    聚合函数+over

    假如说我们想要查询在2015年4月份购买过的顾客及总人数,我们便可以使用窗口函数去去实现

    select name,count(*) over ()
    from t_window
    where substring(orderdate,1,7) = '2015-04'
    

    得到的结果如下:

    name    count_window_0
    mart    5
    mart    5
    mart    5
    mart    5
    jack    5
    

    可见其实在2015年4月一共有5次购买记录,mart购买了4次,jack购买了1次.事实上,大多数情况下,我们是只看去重后的结果的.针对于这种情况,我们有两种实现方式
    第一种:distinct

    select distinct name,count(*) over ()
    from t_window
    where substring(orderdate,1,7) = '2015-04'
    

    第二种:group by

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

    执行后的结果如下:

    name count_window_0 
    mart 2 
    jack 2
    

    partition by子句

    Over子句之后第一个提到的就是Partition By.Partition By子句也可以称为查询分区子句,非常类似于Group By,都是将数据按照边界值分组,而Over之前的函数在每一个分组之内进行,如果超出了分组,则函数会重新计算.

    实例

    我们想要去看顾客的购买明细及月购买总额,可以执行如下的sql

    select name,orderdate,cost,sum(cost) over(partition by month(orderdate))
    from t_window
    

    执行结果如下:

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

    可以看出数据已经按照月进行汇总了.

    order by子句

    上述的场景,假如我们想要将cost按照月进行累加.这时我们引入order by子句.

    order by子句会让输入的数据强制排序(文章前面提到过,窗口函数是SQL语句最后执行的函数,因此可以把SQL结果集想象成输入数据)。Order By子句对于诸如Row_Number(),Lead(),LAG()等函数是必须的,因为如果数据无序,这些函数的结果就没有任何意义。因此如果有了Order By子句,则Count(),Min()等计算出来的结果就没有任何意义。

    我们在上面的代码中加入order by

    select name,orderdate,cost,sum(cost) over(partition by month(orderdate) order by orderdate )
    from t_window
    

    得到的结果如下:(order by默认情况下聚合从起始行到当前行的数据)

    name    orderdate   cost    sum_window_0
    jack    2015-01-01  10  10
    tony    2015-01-02  15  25 //10+15
    tony    2015-01-04  29  54 //10+15+29
    jack    2015-01-05  46  100 //10+15+29+46
    tony    2015-01-07  50  150
    jack    2015-01-08  55  205
    jack    2015-02-03  23  23
    jack    2015-04-06  42  42
    mart    2015-04-08  62  104
    mart    2015-04-09  68  172
    mart    2015-04-11  75  247
    mart    2015-04-13  94  341
    neil    2015-05-10  12  12
    neil    2015-06-12  80  80
    

    window子句

    我们在上面已经通过使用partition by子句将数据进行了分组的处理.如果我们想要更细粒度的划分,我们就要引入window子句了.

    我们首先要理解两个概念:

    • 如果只使用partition by子句,未指定order by的话,我们的聚合是分组内的聚合. 使用了order
    • by子句,未使用window子句的情况下,默认从起点到当前行.

    当同一个select查询中存在多个窗口函数时,他们相互之间是没有影响的.每个窗口函数应用自己的规则.

    • window子句:
    • PRECEDING:往前
    • FOLLOWING:往后
    • CURRENT ROW:当前行
    • UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED
      FOLLOWING:表示到后面的终点

    我们按照name进行分区,按照购物时间进行排序,做cost的累加.
    如下我们结合使用window子句进行查询

    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_window;
    

    得到查询结果如下:

    name    orderdate   cost    sample1 sample2 sample3 sample4 sample5 sample6 sample7
    jack    2015-01-01  10  661 176 10  10  10  56  176
    jack    2015-01-05  46  661 176 56  56  56  111 166
    jack    2015-01-08  55  661 176 111 111 101 124 120
    jack    2015-02-03  23  661 176 134 134 78  120 65
    jack    2015-04-06  42  661 176 176 176 65  65  42
    mart    2015-04-08  62  661 299 62  62  62  130 299
    mart    2015-04-09  68  661 299 130 130 130 205 237
    mart    2015-04-11  75  661 299 205 205 143 237 169
    mart    2015-04-13  94  661 299 299 299 169 169 94
    neil    2015-05-10  12  661 92  12  12  12  92  92
    neil    2015-06-12  80  661 92  92  92  92  92  80
    tony    2015-01-02  15  661 94  15  15  15  44  94
    tony    2015-01-04  29  661 94  44  44  44  94  79
    tony    2015-01-07  50  661 94  94  94  79  79  50
    

    窗口函数中的序列函数

    主要序列函数是不支持window子句的.

    hive中常用的序列函数有下面几个:

    NTILE

    • NTILE(n),用于将分组数据按照顺序切分成n片,返回当前切片值
    • NTILE不支持ROWS BETWEEN, 比如 NTILE(2) OVER(PARTITION BY cookieid ORDER BY
      createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
    • 如果切片不均匀,默认增加第一个切片的分布

    这个函数用什么应用场景呢?假如我们想要每位顾客购买金额前1/3的交易记录,我们便可以使用这个函数.

    select name,orderdate,cost,
           ntile(3) over() as sample1 , --全局数据切片
           ntile(3) over(partition by name), -- 按照name进行分组,在分组内将数据切成3份
           ntile(3) over(order by cost),--全局按照cost升序排列,数据切成3份
           ntile(3) over(partition by name order by cost ) --按照name分组,在分组内按照cost升序排列,数据切成3份
    from t_window
    

    得到的数据如下:

    name    orderdate   cost    sample1 sample2 sample3 sample4
    jack    2015-01-01  10  3   1   1   1
    jack    2015-02-03  23  3   1   1   1
    jack    2015-04-06  42  2   2   2   2
    jack    2015-01-05  46  2   2   2   2
    jack    2015-01-08  55  2   3   2   3
    mart    2015-04-08  62  2   1   2   1
    mart    2015-04-09  68  1   2   3   1
    mart    2015-04-11  75  1   3   3   2
    mart    2015-04-13  94  1   1   3   3
    neil    2015-05-10  12  1   2   1   1
    neil    2015-06-12  80  1   1   3   2
    tony    2015-01-02  15  3   2   1   1
    tony    2015-01-04  29  3   3   1   2
    tony    2015-01-07  50  2   1   2   3
    

    如上述数据,我们去sample4 = 1的那部分数据就是我们要的结果

    row_number
    rank
    dense_rank

    • 这三个窗口函数的使用场景非常多
    • row_number()从1开始,按照顺序,生成分组内记录的序列,row_number()的值不会存在重复,当排序的值相同时,按照表中记录的顺序进行排列
    • RANK() 生成数据项在分组中的排名,排名相等会在名次中留下空位 DENSE_RANK()
      生成数据项在分组中的排名,排名相等会在名次中不会留下空位
      注意:
      rank和dense_rank的区别在于排名相等时会不会留下空位.

      举例如下:
    SELECT 
    cookieid,
    createtime,
    pv,
    RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn1,
    DENSE_RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn2,
    ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY pv DESC) AS rn3 
    FROM lxw1234 
    WHERE cookieid = 'cookie1';
     
    cookieid day           pv       rn1     rn2     rn3 
     
    cookie1 2015-04-12      7       1       1       1
    cookie1 2015-04-11      5       2       2       2
    cookie1 2015-04-15      4       3       3       3
    cookie1 2015-04-16      4       3       3       4
    cookie1 2015-04-13      3       5       4       5
    cookie1 2015-04-14      2       6       5       6
    cookie1 2015-04-10      1       7       6       7
    rn1: 15号和16号并列第3, 13号排第5
    rn2: 15号和16号并列第3, 13号排第4
    rn3: 如果相等,则按记录值排序,生成唯一的次序,如果所有记录值都相等,或许会随机排吧。
    

    LAG和LEAD函数

    这两个函数为常用的窗口函数,可以返回上下数据行的数据.
    以我们的订单表为例,假如我们想要查看顾客上次的购买时间可以这样去查询

    select name,orderdate,cost,
    lag(orderdate,1,'1900-01-01') over(partition by name order by orderdate ) as time1,
    lag(orderdate,2) over (partition by name order by orderdate) as time2
    from t_window;
    

    查询后的数据为:

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

    time1取的为按照name进行分组,分组内升序排列,取上一行数据的值,见下图。

    time2取的为按照name进行分组,分组内升序排列,取上面2行的数据的值,注意当lag函数未设置行数值时,默认为1行.设定取不到时的默认值时,取null值.

    lead函数与lag函数方向相反,取向下的数据.
    在这里插入图片描述

    first_value和last_value

    first_value取分组内排序后,截止到当前行,第一个值
    last_value取分组内排序后,截止到当前行,最后一个值

    select name,orderdate,cost,
    first_value(orderdate) over(partition by name order by orderdate) as time1,
    last_value(orderdate) over(partition by name order by orderdate) as time2
    from t_window
    

    查询结果如下:

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

    原文参考:https://blog.csdn.net/qq_26937525/article/details/54925827

    扩展:

    • row_number的用途非常广泛,排序最好用它,它会为查询出来的每一行记录生成一个序号,依次排序且不会重复,注意使用row_number函数时必须要用over子句选择对某一列进行排序才能生成序号。
    • rank函数用于返回结果集的分区内每行的排名,行的排名是相关行之前的排名数加一。简单来说rank函数就是对查询出来的记录进行排名,与row_number函数不同的是,rank函数考虑到了over子句中排序字段值相同的情况,如果使用rank函数来生成序号,over子句中排序字段值相同的序号是一样的,后面字段值不相同的序号将跳过相同的排名号排下一个,也就是相关行之前的排名数加一,可以理解为根据当前的记录数生成序号,后面的记录依此类推。
    • dense_rank函数的功能与rank函数类似,dense_rank函数在生成序号时是连续的,而rank函数生成的序号有可能不连续。dense_rank函数出现相同排名时,将不跳过相同排名号,rank值紧接上一次的rank值。在各个分组内,rank()是跳跃排序,有两个第一名时接下来就是第四名,dense_rank()是连续排序,有两个第一名时仍然跟着第二名。

    借助实例能更直观地理解:

    假设现在有一张学生表student,学生表中有姓名、分数、课程编号。

    select * from student;
    

    在这里插入图片描述
    现在需要按照课程对学生的成绩进行排序:

    --row_number() 顺序排序
    select name,course,row_number() over(partition by course order by score desc) rank from student;
    
    --rank() 跳跃排序,如果有两个第一级别时,接下来是第三级别
    select name,course,rank() over(partition by course order by score desc) rank from student;
    
    --dense_rank() 连续排序,如果有两个第一级别时,接下来是第二级别 
    select name,course,dense_rank() over(partition by course order by score desc) rank from student;
    

    取得每门课程的第一名:

    --每门课程第一名只取一个: 
    select * from (select name,course,row_number() over(partition by course order by score desc) rank from student) where rank=1;
    --每门课程第一名取所有: 
    select * from (select name,course,dense_rank() over(partition by course order by score desc) rank from student) where rank=1;
    --每门课程第一名取所有:
    select * from (select name,course,rank() over(partition by course order by score desc) rank from student) where rank=1;
    

    附:每门课程第一名取所有的其他方法(使用group by 而不是partition by):

    select s.* from student s
      inner join(select course,max(score) as score from student group by course) c
      on s.course=c.course and s.score=c.score; 
    --或者使用using关键字简化连接
    select * from student s
      inner join(select course,max(score) as score from student group by course) c
      using(course,score);
    

    关于Parttion by:

    Parttion by关键字是Oracle中分析性函数的一部分,用于给结果集进行分区。它和聚合函数Group by不同的地方在于它只是将原始数据进行名次排列,能够返回一个分组中的多条记录(记录数不变),而Group by是对原始数据进行聚合统计,一般只有一条反映统计值的结果(每组返回一条)。

    TIPS:

    使用rank over()的时候,空值是最大的,如果排序字段为null, 可能造成null字段排在最前面,影响排序结果。

    可以这样: rank over(partition by course order by score desc nulls last)

    总结:

    在使用排名函数的时候需要注意以下三点:

    1、排名函数必须有 OVER 子句。

    2、排名函数必须有包含 ORDER BY 的 OVER 子句。

    3、分组内从1开始排序。

    参考:https://www.cnblogs.com/qiuting/p/7880500.html

    展开全文
  • Hive窗口函数Over和排序函数Rank划重点简介概念数据准备实例聚合函数+overpartition by子句order by子句window子句`★`窗口函数中的序列函数NTILE`★`row_number、rank、dense_rankLAG和LEAD函数first_value 和 last...

    划重点

    1、聚合函数+over

    2、partition by子句

    3、order by子句

    4、★window子句(里面包含) - PRECEDING:往前 - FOLLOWING:往后 - CURRENT ROW:当前行 - UNBOUNDED:起点

    5、★窗口函数中的序列函数:包含NTILE(n),row_number、rank、dense_rank

    简介

    本文主要介绍hive中的窗口函数.hive中的窗口函数和sql中的窗口函数相类似,都是用来做一些数据分析类的工作,一般用于olap分析

    注意:OVER():指定分析函数工作的数据窗口大小,决定了聚合函数的范围,这个数据窗口大小可能会随着行的变而变化,同时可以使用以下进行限定范围。

    概念

    我们都知道在sql中有一类函数叫做聚合函数,例如sum()、avg()、max()等等,这类函数可以将多行数据按照规则聚集为一行,一般来讲聚集后的行数是要少于聚集前的行数的.但是有时我们想要既显示聚集前的数据,又要显示聚集后的数据,这时我们便引入了窗口函数.

    在深入研究Over字句之前,一定要注意:在SQL处理中,窗口函数都是最后一步执行,而且仅位于Order by字句之前.

    数据准备

    我们准备一张order表(文件名order.txt),字段分别为name,orderdate,cost.数据内容如下:

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

    在hive中建立一张表t_window,将数据插入进去.

    create table if not exists t_window(
    name string,
    orderdate date,
    cost int)
    row format delimited 
    fields terminated by ',' 
    lines terminated by '\n';
    

    上传数据文件

    [david_admin@server111-111-111-111 over_func_test]$ hive -e "load data local inpath '/home/david_admin/hive_test/over_func_test/order.txt' into table t_window"
    

    实例

    聚合函数+over

    假如说我们想要查询在2015年4月份购买过的顾客及总人数,我们便可以使用窗口函数去去实现

    select name,count(*) over ()
    from t_window
    where substring(orderdate,1,7) = '2015-04'
    

    得到的结果如下:

    name    count_window_0
    mart    5
    mart    5
    mart    5
    mart    5
    jack    5
    

    可见其实在2015年4月一共有5次购买记录,mart购买了4次,jack购买了1次.事实上,大多数情况下,我们是只看去重后的结果的.针对于这种情况,我们有两种实现方式

    第一种:distinct

    select distinct name,count(*) over ()
    from t_window
    where substring(orderdate,1,7) = '2015-04'
    

    第二种:group by

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

    执行后的结果如下:

    name count_window_0 
    mart 2 
    jack 2
    

    partition by子句

    Over子句之后第一个提到的就是Partition By.Partition By子句也可以称为查询分区子句,非常类似于Group By,都是将数据按照边界值分组,而Over之前的函数在每一个分组之内进行,如果超出了分组,则函数会重新计算.

    实例
    我们想要去看顾客的购买明细及月购买总额,可以执行如下的sql

    select name,orderdate,cost,sum(cost) over(partition by month(orderdate))
    from t_window
    

    执行结果如下:

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

    可以看出数据已经按照月进行[解释:当月按天排序后,按天累加]汇总了.

    order by子句

    上述的场景,假如我们想要将cost按照月进行累加.这时我们引入order by子句.

    order by子句会让输入的数据强制排序(文章前面提到过,窗口函数是SQL语句最后执行的函数,因此可以把SQL结果集想象成输入数据)。Order By子句对于诸如Row_Number(),Lead(),LAG()等函数是必须的,因为如果数据无序,这些函数的结果就没有任何意义。因此如果有了Order By子句,则Count(),Min()等计算出来的结果就没有任何意义

    我们在上面的代码中加入order by

    select name,orderdate,cost,sum(cost) over(partition by month(orderdate) order by orderdate )
    from t_window
    

    得到的结果如下:(order by默认情况下聚合从起始行当当前行的数据)

    name    orderdate   cost    sum_window_0
    jack    2015-01-01  10  10
    tony    2015-01-02  15  25
    tony    2015-01-04  29  54
    jack    2015-01-05  46  100
    tony    2015-01-07  50  150
    jack    2015-01-08  55  205
    jack    2015-02-03  23  23
    jack    2015-04-06  42  42
    mart    2015-04-08  62  104
    mart    2015-04-09  68  172
    mart    2015-04-11  75  247
    mart    2015-04-13  94  341
    neil    2015-05-10  12  12
    neil    2015-06-12  80  80
    

    window子句

    我们在上面已经通过使用partition by子句将数据进行了分组的处理.如果我们想要更细粒度的划分,我们就要引入window子句了.

    我们首先要理解两个概念:

    • 如果只使用partition by子句,未指定order by的话,我们的聚合是分组内的聚合.
    • 使用了order by子句,未使用window子句的情况下,默认从起点到当前行.

    当同一个select查询中存在多个窗口函数时,他们相互之间是没有影响的.每个窗口函数应用自己的规则.

    window子句:

    • PRECEDING:往前
    • FOLLOWING:往后
    • CURRENT ROW:当前行
    • UNBOUNDED:起点; UNBOUNDED PRECEDING 表示从前面的起点; UNBOUNDED FOLLOWING:表示到后面的终点

    我们按照name进行分区,按照购物时间进行排序,做cost的累加.

    如下我们结合使用window子句进行查询

    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_window;
    

    得到查询结果如下:

    name    orderdate   cost    sample1 sample2 sample3 sample4 sample5 sample6 sample7
    jack    2015-01-01  10  661 176 10  10  10  56  176
    jack    2015-01-05  46  661 176 56  56  56  111 166
    jack    2015-01-08  55  661 176 111 111 101 124 120
    jack    2015-02-03  23  661 176 134 134 78  120 65
    jack    2015-04-06  42  661 176 176 176 65  65  42
    mart    2015-04-08  62  661 299 62  62  62  130 299
    mart    2015-04-09  68  661 299 130 130 130 205 237
    mart    2015-04-11  75  661 299 205 205 143 237 169
    mart    2015-04-13  94  661 299 299 299 169 169 94
    neil    2015-05-10  12  661 92  12  12  12  92  92
    neil    2015-06-12  80  661 92  92  92  92  92  80
    tony    2015-01-02  15  661 94  15  15  15  44  94
    tony    2015-01-04  29  661 94  44  44  44  94  79
    tony    2015-01-07  50  661 94  94  94  79  79  50
    

    窗口函数中的序列函数

    主要序列函数是不支持window子句的.

    hive中常用的序列函数有下面几个:

    NTILE

    • NTILE(n),用于将分组数据按照顺序切分成n片,返回当前切片值

    • NTILE不支持ROWS BETWEEN,
      比如 NTILE(2) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)

    • 如果切片不均匀,默认增加第一个切片的分布

    这个函数用什么应用场景呢?

    案例①:
    假如我们想要每位顾客购买金额前1/3的交易记录,我们便可以使用这个函数.

    select name,orderdate,cost,
           ntile(3) over() AS sample1 , --全局数据切片
           ntile(3) over(partition by name) AS sample2 , -- 按照name进行分组,在分组内将数据切成3份
           ntile(3) over(order by cost) AS sample3,--全局按照cost升序排列,数据切成3份
           ntile(3) over(partition by name order by cost ) AS sample4 --按照name分组,在分组内按照cost升序排列,数据切成3份
    from t_window
    

    得到的数据如下:

    name    orderdate   cost    sample1 sample2 sample3 sample4
    jack    2015-01-01  10  3   1   1   1
    jack    2015-02-03  23  3   1   1   1
    jack    2015-04-06  42  2   2   2   2
    jack    2015-01-05  46  2   2   2   2
    jack    2015-01-08  55  2   3   2   3
    mart    2015-04-08  62  2   1   2   1
    mart    2015-04-09  68  1   2   3   1
    mart    2015-04-11  75  1   3   3   2
    mart    2015-04-13  94  1   1   3   3
    neil    2015-05-10  12  1   2   1   1
    neil    2015-06-12  80  1   1   3   2
    tony    2015-01-02  15  3   2   1   1
    tony    2015-01-04  29  3   3   1   2
    tony    2015-01-07  50  2   1   2   3
    

    如上述数据,我们去sample4 = 1的那部分数据就是我们要的结果

    案例②:
    全部订单记录按购买金额由高到低二等分后, 统计前1/2, 和后 1/2 的交易平均值.

    with two_sep as (select name,orderdate,cost,
        ntile(2) over(order by cost desc) as rn
        from t_window
    ), avg_payment_up_50 as (
    	select  avg(cost) as avg_payment_up_50   from two_sep where rn = 1
    ), avg_payment_down_50 as (
    	select  avg(cost) as avg_payment_down_50 from two_sep where rn = 2
    )
    select 
    	T1.avg_payment_up_50, 
    	T2.avg_payment_down_50
    from avg_payment_up_50 T1
    join avg_payment_down_50 T2
    on 1 = 1 ;
    
    统计结果如下:
    t1.avg_payment_up_50	t2.avg_payment_down_50
    69.14285714285714		25.285714285714285
    

    row_number、rank、dense_rank

    ※ 这三个窗口函数的使用场景非常多 ※

    • row_number()从1开始,按照顺序,生成分组内记录的序列,row_number()的值不会存在重复,当排序的值相同时,按照表中记录的顺序进行排列
    • RANK() 生成数据项在分组中的排名,排名相等会在名次中留下空位
    • DENSE_RANK() 生成数据项在分组中的排名,排名相等会在名次中不会留下空位

    **注意:
    rank和dense_rank的区别在于排名相等时会不会留下空位.

    准备数据文件(cookies.txt):

    cookie1	2015-04-12	7
    cookie1	2015-04-11	5
    cookie1	2015-04-15	4
    cookie1	2015-04-16	4
    cookie1	2015-04-13	3
    cookie1	2015-04-14	2
    cookie1	2015-04-10	1
    

    在hive中建立一张表t_window,将数据插入进去.

    create table if not exists t_cookies(
    cookieid string,
    day date,
    pv int)
    row format delimited 
    fields terminated by '\t' 
    lines terminated by '\n';
    

    上传数据文件

    [david_admin@server111-111-111-111 over_func_test]$ $ hive -e "load data local inpath '/home/david_admin/hive_test/over_func_test/cookies.txt' into table t_cookies"
    

    举例如下:

    SELECT 
    cookieid,
    createtime,
    pv,
    RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn1,
    DENSE_RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn2,
    ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY pv DESC) AS rn3 
    FROM t_cookies 
    WHERE cookieid = 'cookie1';
    
    cookieid day           pv       rn1     rn2     rn3 
    ----------------------------------------------------------
    cookie1 2015-04-12      7       1       1       1
    cookie1 2015-04-11      5       2       2       2
    cookie1 2015-04-15      4       3       3       3
    cookie1 2015-04-16      4       3       3       4
    cookie1 2015-04-13      3       5       4       5
    cookie1 2015-04-14      2       6       5       6
    cookie1 2015-04-10      1       7       6       7
    
    rn1: 15号和16号并列第3, 13号排第5
    rn2: 15号和16号并列第3, 13号排第4
    rn3: 如果相等,则按记录值排序,生成唯一的次序,如果所有记录值都相等,或许会随机排吧。
    

    LAG和LEAD函数

    这两个函数为常用的窗口函数,可以返回上下数据行的数据.
    以我们的订单表为例,假如我们想要查看顾客上次的购买时间可以这样去查询

    select name,orderdate,cost,
    lag(orderdate,1,'1900-01-01') over(partition by name order by orderdate ) as time1,
    lag(orderdate,2) over (partition by name order by orderdate) as time2
    from t_window;
    

    查询后的数据为:

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

    time1取的为按照name进行分组,分组内升序排列,取上一行数据的值.

    time2取的为按照name进行分组,分组内升序排列,取上面2行的数据的值,注意当lag函数为设置行数值时,默认为1行.未设定取不到时的默认值时,取null值.

    lead函数与lag函数方向相反,取向下的数据.

    first_value 和 last_value

    • first_value取分组内排序后,截止到当前行,第一个值
    • last_value取分组内排序后,截止到当前行,最后一个值
    select name,orderdate,cost,
    first_value(orderdate) over(partition by name order by orderdate) as time1,
    last_value(orderdate) over(partition by name order by orderdate) as time2
    from t_window
    

    查询结果如下:

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

    参考内容:

    展开全文
  • hive 窗口函数 应用场景与实战详解

    千次阅读 2016-06-23 18:40:31
    下面就结合具体的需求与实例,一一为大家讲解窗口函数的使用方法。1.数据准备先在hive数据库中建一张表,表的结构如下:hive (tmp)> desc phone_test; OK calling_num string called_num string准备测试文件

    项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
    欢迎大家star,留言,一起学习进步

    hive中的窗口函数,功能非常强大,使用也比较方便,可以给我们的查询提供相当多的遍历。下面就结合具体的需求与实例,一一为大家讲解窗口函数的使用方法。

    1.数据准备

    先在hive数据库中建一张表,表的结构如下:

    hive (tmp)> desc phone_test;
    OK
    calling_num         	string
    called_num          	string
    

    准备测试文件:

    vim phone
    130,131
    130,131
    130,131
    130,131
    130,131
    130,131
    130,132
    130,132
    130,133
    130,133
    130,134
    132,130
    132,130
    132,130
    132,130
    132,130
    132,131
    132,131
    132,131
    132,133
    132,133
    132,133
    134,135
    134,135
    134,135
    134,135
    134,136
    134,136
    134,136
    138,137
    138,137
    138,137
    138,136
    138,136
    135,130
    135,130
    135,130
    135,130
    135,132
    135,132
    

    将文件put到hdfs中hive表对应的位置:

    hadoop fs -put phone /data/hive/warehouse/tmp.db/phone_test
    

    至此,数据准备工作完毕。

    2.row_num()方法,最有用的窗口函数,或许没有之一

    表phone_test的第一列为主叫电话,第二列为被叫电话,我们经常有这种需求:对于同一主叫电话,按通话次数的多少(即被叫电话)进行排序。这个时候row_num()方法就派上了用场。请看:

    select a.calling_num,called_num,count,
    row_number() OVER (distribute BY calling_num sort BY count DESC) rn
    from
    (select calling_num,called_num,count(*) as count
    from phone_test group by calling_num,called_num)a
    
    130	131	6	1
    130	133	2	2
    130	132	2	3
    130	134	1	4
    132	130	5	1
    132	133	3	2
    132	131	3	3
    134	135	4	1
    134	136	3	2
    138	137	3	1
    138	136	2	2
    135	130	4	1
    135	132	2	2
    

    最后一列,就是在同一主叫电话中,被叫电话与主叫电话通话次数的排序。怎么样,很方便吧。
    如果要取通话最多的那个,在此基础上稍作改动:

    select b.calling_num,called_num,count
    from
    (select a.calling_num,called_num,count,
    row_number() OVER (distribute BY calling_num sort BY count DESC) rn
    from
    (select calling_num,called_num,count(*) as count
    from phone_test group by calling_num,called_num)a)b
    where b.rn = 1
    
    130	131	6
    132	130	5
    134	135	4
    138	137	3
    135	130	4
    

    这样就把每组中rn=1的那一行给选了出来。

    换一种写法,还可以这么写:

    select b.calling_num,called_num,count
    from
    (select a.calling_num,called_num,count,
    row_number() OVER (partition BY calling_num order BY count DESC) rn
    from
    (select calling_num,called_num,count(*) as count
    from phone_test group by calling_num,called_num)a)b
    where b.rn = 1
    
    130	131	6
    132	130	5
    134	135	4
    138	137	3
    135	130	4
    

    效果与前面是一样一样滴!

    3.rank() dense_rank()

    rank,顾名思义,就是排序啦。这个比排序更高级一点的是,返回的数据项是在分组中的排名,排名相等的会在名词中留下对应的空位。而dense_rank与rank唯一的不同,就是排名相等的时候不会留下对应的空位。
    看例子:

    select a.calling_num,called_num,count,
    rank() over (partition by calling_num order by count desc) rank,
    dense_rank() over (partition by calling_num order by count desc) drank,
    row_number() OVER (distribute BY calling_num sort BY count DESC) rn
    from
    (select calling_num,called_num,count(*) as count
    from phone_test group by calling_num,called_num)a
    
    对应结果的列为:calling_num called_num count rank drank rn
    130	131	6	1	1	1
    130	133	2	2	2	2
    130	132	2	2	2	3
    130	134	1	4	3	4
    132	130	5	1	1	1
    132	133	3	2	2	2
    132	131	3	2	2	3
    134	135	4	1	1	1
    134	136	3	2	2	2
    138	137	3	1	1	1
    138	136	2	2	2	2
    135	130	4	1	1	1
    135	132	2	2	2	2
    

    聪明的你,是不是已经明白这两个函数的用法了?

    4.ntile()

    ntile是按层次查询。其作用是将数据分成几部分,例如我们想把数据总共分为十份,我们想取前10%来做分析。请看:

    select calling_num,called_num,count(*),ntile(5) over(order by count(*) desc) til
    from phone_test group by calling_num,called_num
    130	131	6	1
    132	130	5	1
    135	130	4	1
    134	135	4	2
    138	137	3	2
    132	133	3	2
    132	131	3	3
    134	136	3	3
    138	136	2	3
    130	132	2	4
    135	132	2	4
    130	133	2	5
    130	134	1	5
    

    我们先将所有数据分为了5部分。如果只想查看其中某一部分:

    select a.calling_num,a.called_num,count,til from
    (select calling_num,called_num,count(*) count,ntile(5) over(order by count(*) desc) til
    from phone_test group by calling_num,called_num)a
    where til = 1
    
    130	131	6	1
    132	130	5	1
    135	130	4	1
    

    5.一定范围内的聚合

    实际应用场景中,我们有各种数据聚合的要求,而且还比一般的计算要复杂。例如对与电商来说,经常需要看当月与今年之前所有月的累计订单量。对于销售人员来说,也经常需要看当月与今年之前或这个季度之前的累计销售额。对于本文中的例子,我们想计算当前号码的通话总和,以及与之前所有号码通话总和的累计:

    select calling_num,sum(num),
    sum(sum(num)) over(order by calling_num ROWS between unbounded preceding and current row) as cumulative_sum
    from
    (select calling_num,called_num,count(*) as num
    from phone_test group by calling_num,called_num)a
    group by calling_num
    
    130	11	11
    132	11	22
    134	7	29
    135	6	35
    138	5	40
    

    sum(sum(num))这种写法中,里面的sum(num)表示需要累加的和。
    重点看下over里面的内容:
    order by calling_num表示按主叫电话排序
    ROWS between unbounded preceding and current row 肯定就是表示聚合的起始位置与终止位置了。unbounded preceding是起点,表示从第一行开始;current row为默认值,表示到当前行。
    以下写法,能达到同样的效果:

    select calling_num,sum(num),
    sum( sum(num)) over(order by calling_num ROWS unbounded preceding) as cumulative_sum
    from
    (select calling_num,called_num,count(*) as num
    from phone_test group by calling_num,called_num)a
    group by calling_num
    
    130	11	11
    132	11	22
    134	7	29
    135	6	35
    138	5	40
    

    如果只想在当前行对前两行聚合,总共计算前两行+当前行=3行的值,可以这样写:

    select calling_num,sum(num),
    sum( sum(num)) over(order by calling_num ROWS between 2 preceding and current row) as cumulative_sum
    from
    (select calling_num,called_num,count(*) as num
    from phone_test group by calling_num,called_num)a
    group by calling_num
    
    130	11	11
    132	11	22
    134	7	29
    135	6	24
    138	5	18
    

    也可以这么写:

    select calling_num,sum(num),
    sum( sum(num)) over(order by calling_num ROWS 2 preceding) as cumulative_sum
    from
    (select calling_num,called_num,count(*) as num
    from phone_test group by calling_num,called_num)a
    group by calling_num
    
    130	11	11
    132	11	22
    134	7	29
    135	6	24
    138	5	18
    

    如果想对之前一行后面一行进行聚合,总共前面一行+当前行+后面一行=3行计算结果,可以这么写:

    select calling_num,sum(num),
    sum(sum(num)) over(order by calling_num ROWS between 1 preceding and 1 following) as cumulative_sum
    from
    (select calling_num,called_num,count(*) as num
    from phone_test group by calling_num,called_num)a
    group by calling_num
    
    130	11	22
    132	11	29
    134	7	24
    135	6	18
    138	5	11
    
    展开全文
  • Hive窗口函数 准备测试数据 聚合函数+over() 用法描述 用法示例 未指定分组和排序 未指定排序 未指定分组 指定排序和分组 加上window子句 窗口函数 用法描述 LEAD函数和LAG函数 FIRST_VALUE函数和LAST_VALUE函数 ...
  • hive窗口函数(开窗函数)over的使用介绍+实例讲解
  • 样例数据2.ntile(n)2.1实例 1.样例数据 id crtime pv cookie1,2015-04-10,1 cookie1,2015-04-11,5 cookie1,2015-04-12,7 cookie1,2015-04-13,3 cookie1,2015-04-14,2 cookie1,2015-04-15,4 cookie1,2015-04-16,4 ...
  • OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化。 CURRENT ROW:当前行 n PRECEDING:往前n行数据 n FOLLOWING:往后n行数据 UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的...
  • 一、窗口函数的概念 窗口就是数据内部按某个字段分区,在分区内做一些事情。 over() partition_by order_by window函数 row_number() rank() dense_rank() lag() lead() first_value() last_value() 二、实例 建立一...
  • Hive 分析函数lead、lag实例应用

    万次阅读 多人点赞 2015-12-31 15:34:21
    Hive的分析函数又叫窗口函数,在oracle中就有这样的分析函数,主要用来做数据统计分析的。 Lag和Lead分析函数可以在同一次查询中取出同一字段的前N行的数据(Lag)和后N行的数据(Lead)作为独立的列。 这种操作可以代替...
  • Hive ~之窗口函数总结简介概念数据准备实例聚合函数+overpartition by子句order by子句window子句窗口函数中的序列函数NTILELAG和LEAD函数first_value和last_value扩展:总结: 简介 本文主要介绍hive中的窗口函数....
  • hive窗口函数 概述 hive中一般求取TopN时就需要用到窗口函数 专业窗口函数一般有三个 rank() over dense rank() over row_number() over 实例 创建一个f_test表拿到以下数据+------------+--------------+--...
  • 原文:https://www.cnblogs.com/wujin/p/6051768.html row_number()、rank()、dense_rank()三个函数相当于group by 之后再来个order by 上实例 id name sal 1 a 10 2 a 12 3 b 13 4 b 12 5 a 14 6 a 15 7 ...
  • Hive _偏门常用查询函数(一)附带实例 https://blog.csdn.net/qq_41946557/article/details/102904642 列转行 1.函数说明 EXPLODE(col):将hive一列中复杂的array或者map结构拆分成多行。 LATERAL VIEW 用法...
  • 窗口函数

    2020-09-21 17:53:46
    窗口函数简介场景函数 简介 也称分析函数,OLAP函数(Online Anallytical Processing,联机分析函数),窗口函数与分组聚合函数类似,但是每一行数据都生成一个结果。 适用数据平台:hive,Spark,sql server, Oracle, ...
  • 接上两篇博客 Hive _偏门常用查询函数(一)附带实例 ...Hive _偏门常用查询函数(二)附带实例(列转行、窗口函数) https://blog.csdn.net/qq_41946557/article/details/102905208 Rank 1.函数说...
  • 说明:Hive之cube、rollup,还有窗口函数,在传统关系型数据(Oracle、sqlserver)中都是有的,用法都很相似。 GROUPING SETS GROUPING SETS作为GROUP BY的子句,允许开发人员在GROUP BY语句后面指定多个统计选项...
  • hive新功能 Cube, Rollup介绍

    万次阅读 2013-12-08 14:15:02
    说明:hive之cube、rollup,还有窗口函数,在传统关系型数据(oracle、sqlserver)中都是有的,用法都很相似。 GROUPING SETS GROUPING SETS作为GROUP BY的子句,允许开发人员在GROUP BY语句后面指定多个统计选项...
  • 104.实时窗口Window统计详解(reduceByKeyAndWindow使用) 第7章:基于Java和Python的Spark编程 105.基于Java和Python语言的Spark开发的提纲及学习方式 106.基于JAVA语言编写Spark Application编程模板、读取数据...

空空如也

空空如也

1 2
收藏数 29
精华内容 11
关键字:

hive窗口函数实例