窗口函数

  我们都知道在sql中有一类函数叫做聚合函数,例如sum()、avg()、max()等等,

  这类函数可以将多行数据按照规则聚集为一行,一般来讲聚集后的行数是要少于聚集前的行数的.

  但是有时我们想要既显示聚集前的数据,又要显示聚集后的数据,这时我们便引入了窗口函数.

 hive中的窗口函数和sql中的窗口函数相类似,都是用来做一些数据分析类的工作,一般用于olap分析。

  在深入研究Over字句之前,一定要注意:在SQL处理中,窗口函数都是最后一步执行,而且仅位于Order by字句之前.还有窗口函数是对select出来的数据进行处理分析得出来的结果。

  顺序是先select,用select的结果进行窗口函数的处理分析。

1.分析函数

   分析函数主要分为sum avg min max count等

  我们这里主要分析Sum() over() 和 count() over分析函数使用,其他类同

创建测试表

create table test(sales_id varchar2(2),sales varchar2(10),dest varchar2(10),dept varchar2(10),revenue number);

插入测试数据

insert into test values(‘11‘,‘smith‘,‘hangzhou‘,‘市场‘,1000);

insert into test values(‘12‘,‘smith‘,‘wenzhou‘,‘市场‘,2000);

insert into test values(‘13‘,‘allen‘,‘wenzhou‘,‘渠道‘,3000);

insert into test values(‘14‘,‘allen‘,‘wenzhou‘,‘渠道‘,4000);

insert into test values(‘15‘,‘jekch‘,‘shanghai‘,‘渠道‘,2500);

insert into test values(‘11‘,‘smith‘,‘hangzhou‘,‘市场‘,1000);

insert into test values(‘12‘,‘smith‘,‘wenzhou‘,‘市场‘,2000);

commit;

查询所有数据

SQL> select * from test;

SALES_ID    SALES     DEST       DEPT    REVENUE

--------          ---------- ----------     ----------  ----------

11                  smith    hangzhou      市场       1000

12                  smith   wenzhou        市场        2000

13                  allen    wenzhou        渠道       3000

14                  allen    wenzhou        渠道       4000

15                  jekch   shanghai       渠道        2500

11                  smith   hangzhou      市场        1000

12                  smith   wenzhou        市场        2000

用窗口函数计算总销售额

SQL> select sales_id, sales,dest,dept,revenue,

   sum(revenue) over() as 总销售额

from test;

SALES_ID  SALES   DEST   DEPT   REVENUE   总销售额

-------- -     --------- ----------  ----------   ----------    ----------

11               smith   hangzhou 市场      1000         15500

12               smith    wenzhou 市场       2000         15500

13               allen     wenzhou 渠道      3000         15500

14               allen     wenzhou 渠道      4000         15500

15               jekch    shanghai 渠道      2500        15500

11               smith   hangzhou 市场      1000         15500

12               smith    wenzhou 市场       2000         15500

按照sales_id order by排序计算递加的销售总额

SQL> select sales_id,sales,dest,dept,revenue,

     sum(revenue)over(order by sales) 递加销售总额

from test;

SALES_ID    SALES   DEST   DEPT   REVENUE   递加销售总额

--------        ----------   ---------- ---------- ----------      ------------

14                allen     wenzhou 渠道        4000           7000

13                allen     wenzhou 渠道         3000          7000

15                jekch    shanghai 渠道         2500          9500

11                smith   hangzhou 市场         1000         15500

12                smith    wenzhou 市场          2000         15500

12                smith    wenzhou 市场           2000        15500

11                smith   hangzhou 市场          1000         15500

对sales_id进行分组,然后分组求sum

SQL> select sales_id,sales,dest,dept,revenue,

     sum(revenue)over(partition by sales_id) 分组销售总额

from test;

SALES_ID     SALES     DEST    DEPT    REVENUE    分组销售总额

--------          ----------   ----------  ----------  ----------        ------------

11                 smith     hangzhou  市场       1000              2000

11                 smith     hangzhou  市场        1000              2000

12                 smith      wenzhou   市场        2000             4000

12                smith        wenzhou  市场        2000             4000

13                allen        wenzhou   渠道        3000             3000

14                allen         wenzhou  渠道        4000             4000

15                jekch        shanghai  渠道        2500 2500

注意,sum over(partition by) 和 sum group by 的区别是什么?

    sum over(partition by) 是先select,然后进行窗口函数,这是一对一的。这里所有的数据都在,并没有合并,只是多出来一个窗口函数分析的数据列。

   sum group by 则是先分组聚合,多变成了一,显示的并不是全部数据,而是聚合后求sum的数据。

对sales进行分组,然后分组内递加sum。

SQL> select sales_id,sales,dest,dept,revenue,

sum(revenue)over(partition by sales order by sales_id) 分组递加销售总额

from test;

SALES_ID      SALES     DEST      DEPT    REVENUE     分组递加销售总额

--------          ----------    ---------- ----------  ----------           ----------------

13                   allen         wenzhou 渠道         3000              3000

14                   allen         wenzhou 渠道         4000              7000

15                   jekch        shanghai 渠道         2500              2500

11                   smith        hangzhou 市场        1000              2000

11                   smith        hangzhou 市场        1000              2000

12                   smith        wenzhou 市场          2000             6000

12                   smith         wenzhou 市场         2000             6000

看下来的count()over()分析函数的使用

SQL> select sales_id,sales,

     count(*)over() 求总计数,

count(*)over(order by sales_id) 递加求计数,

count(*)over(partition by sales_id) 分组求计数,

count(*)over(partition by sales_id order by sales) 分组递加求计数

from test;

SALES_ID     SALES    求总计数    递加求计数    分组求计数   分组递加求计数

--------         ----------      ----------      ----------         ----------       --------------

11                   smith           7                2                    2                     2

11                   smith           7                2                    2                     2

12                   smith           7               4                     2                     2

12                   smith           7               4                     2                     2

13                   allen            7               5                     1                     1

14                   allen            7               6                     1                     1

15                   jekch           7               7                     1                     1

如果我们想要更细粒度的划分,我们就要引入window子句了.

我们首先要理解两个概念:
- 如果只使用partition by子句,未指定order by的话,我们的聚合是分组内的聚合.
- 使用了order by子句,未使用window子句的情况下,默认从起点到当前行.

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

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

sum(revenue)over(partition by sales order by sales_id ROWS between UNBOUNDED PRECEDING and CURRENT ROW);

  由起点到当前行,默认也是由起点到当前行,做聚合

sum(revenue)over(partition by sales order by sales_id ROWS between 1  PRECEDING and CURRENT ROW);

  当前行到前面一行做聚合

sum(revenue)over(partition by sales order by sales_id ROWS between 1  PRECEDING and 1 FOLLOWING);

  当前一行到前面一行做聚合

sum(revenue)over(partition by sales order by sales_id ROWS between CURRENT ROW  and UNBOUNDED PRECEDING);

  当前行到后边所有行做聚合

2.序列函数

  主要序列函数是不支持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)
    • 如果切片不均匀,默认增加第一个切片的分布  

select sales_id, sales,dest,dept,revenue,

   sum(revenue)  NTILE(1) over() as 总销售额

from test;

row_number、rank、dense_rank

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

    select sales_id,sales,dest,dept,revenue,

RANK() over(partition by sales order by sales_id) 分组递加销售总额

from test;

LAG和LEAD函数

这两个函数为常用的窗口函数,可以返回上下数据行的数据.

first_value和last_value

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

原文地址:https://www.cnblogs.com/zzhangyuhang/p/8671579.html

时间: 2024-11-07 07:30:22

窗口函数的相关文章

Hive分析窗口函数

Hive分析窗口函数(四) LAG,LEAD,FIRST_VALUE,LAST_VALUE https://cwiki.apache.org/confluence/display/Hive/LanguageManual+WindowingAndAnalytics

Oracle开发之窗口函数 rows between unbounded preceding and current row

目录=========================================1.窗口函数简介2.窗口函数示例-全统计3.窗口函数进阶-滚动统计(累积/均值)4.窗口函数进阶-根据时间范围统计5.窗口函数进阶-first_value/last_value6.窗口函数进阶-比较相邻记录 一.窗口函数简介: 到目前为止,我们所学习的分析函数在计算/统计一段时间内的数据时特别有用,但是假如计算/统计需要随着遍历记录集的每一条记录而进行呢?举些例子来说: ①列出每月的订单总额以及全年的订单总额②

窗口函数 RANK

最近一直在了解与学习sqlserver 窗口函数的各种知识,发现窗口函数能够很方便实现在之前可能需要关联子查询等一些复杂的逻辑才能实现的逻辑,下边是自己的一些学习笔记. RANK函数:从小到大,每次最苦逼的就是考试了,肿么都会有一个结果排名,张三数学第一,李四.小明并列第二....这应该是我们最早接触到的排名概念,sqlserver 中rank 也是这样的意思,和row_number() 区别就是rownum会为每个分区值相同的去一个随机排名,即排名不会存在并列的情况 创建一个数据表:包含班级编

Spark窗口函数应用(-)

/** * @author DT大数据梦工厂 * 新浪微博 http://weibo.com/ilovepains/ * 微信公众账号:DT_Spark * 直播地址 YY频道:68917580 */object SparkSQLWindowFunctionOps { def main(args: Array[String]) { /** * 创建SparkConf对象,设置Spark程序运行时的配置信息 * 例如说通过setMaster来设置程序要链接的Spark集群的Master的URL,如

窗口函数 ROW_NUMBER

ROW_NUMBER:在窗口函数的分区.排序列 会为每一数据行分配唯一的序列值 最近在工作中经常会碰到,计算当前订单时该会员的第多少单以及会员的累积消费金额等情况 1:计算会员当前订单是该会员第几单(根据订单创建时间计算) 1 SELECT OrderCode , 2 CustCode , 3 OrderMoney , 4 CreateTime , 5 ROW_NUMBER() OVER ( ORDER BY CreateTime ) AS OrderSeq 6 FROM dbo.Sales_O

hive内置函数详解(分析函数、窗口函数)

cli命令 show functions; desc function concat; desc function extended concat;查看某个函数怎么使用的例子 nvl函数coalesce(v1,v2,...)返回参数中第一个非空值,如果所有值都为null返回null: set.cli.print.header=true; winfunc 员工 工资 标识 id  money type 关系型运算符优先级高到低为:not and orand or 优先级 select id ,mo

窗口函数ntile()

一直没实际的需求而使用ntile(),今天看了下,就是按序号分组的意思. 还是以student表为例 select ntile(3) over (order by score desc) as zu, name, score, province from student 一共13行数据,分三组,第一组就是5: 那我们看分成五组结果如何呢? 分成五个组,前面1,2,3组是三个,后面两个组是2个. 还可以使用ntile() over (partition by province order by s

MySQL 以及 Python 实现排名窗口函数

大部分数据库都提供了窗口函数,比如RANK,ROW_NUMBER等等. MySQL 这方面没有直接提供,但是可以变相的实现,我以前写了row_number 的实现,今天有时间把 rank 的实现贴出来. 这里,我用MySQL 以及Python 分别实现了rank 窗口函数.原始表信息: t_girl=# \d group_concat; Table "ytt.group_concat" Column | Type | Modifiers ----------+-------------

添加分区以及分析函数和窗口函数

一:添加分区 1.查看表的分区 2.手动添加分区 3.关于分区表的查询 二:分析函数和窗口函数 1.将要操作的数据表示emp 2.部门10的部门分组,按照薪资降序排列 3.所有的部门分组,并且按照薪资降序排列,同时最后一列显示每组的最值 4.所有的部门分组,并且按照薪资降序排列,同时最后一列显示每组的行号

把消息送到默认窗口函数里,并非一点用都没有,可能会产生新的消息(以WM_WINDOWPOSCHANGED为例)

我在追踪执行: procedure TForm1.Button1Click(Sender: TObject); begin panel1.Left:=panel1.Left-10; end; 并且屏蔽TWinControl.WMWindowPosChanged里的UpdateBounds函数后 procedure TWinControl.WMWindowPosChanged(var Message: TWMWindowPosChanged); var Framed, Moved, Sized: