开窗函数:定义 行 为 列
简单讲,就是在你查询的结果上,直接多出一列值(可以是聚合值或是排序号),特征就是带有 over()。
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
row_number、rank、dense_rank
- row_number()从1开始,按照顺序,生成分组内记录的序列,row_number()的值不会存在重复,当排序的值相同时,按照表中记录的顺序进行排列
 - RANK() 生成数据项在分组中的排名,排名相等会在名次中留下空位
 - DENSE_RANK() 生成数据项在分组中的排名,排名相等会在名次中不会留下空位
 
rank和dense_rank的区别在于排名相等时会不会留下空位.**
SELECTcookieid,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 rn3FROM lxw1234WHERE cookieid = 'cookie1';cookieid day pv rn1 rn2 rn3cookie1 2015-04-12 7 1 1 1cookie1 2015-04-11 5 2 2 2cookie1 2015-04-15 4 3 3 3cookie1 2015-04-16 4 3 3 4cookie1 2015-04-13 3 5 4 5cookie1 2015-04-14 2 6 5 6cookie1 2015-04-10 1 7 6 7rn1: 15号和16号并列第3, 13号排第5rn2: 15号和16号并列第3, 13号排第4rn3: 如果相等,则按记录值排序,生成唯一的次序,如果所有记录值都相等,或许会随机排吧。
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 time2from t_window;name orderdate cost time1 time2jack 2015-01-01 10 1900-01-01 NULLjack 2015-01-05 46 2015-01-01 NULLjack 2015-01-08 55 2015-01-05 2015-01-01jack 2015-02-03 23 2015-01-08 2015-01-05jack 2015-04-06 42 2015-02-03 2015-01-08mart 2015-04-08 62 1900-01-01 NULLmart 2015-04-09 68 2015-04-08 NULLmart 2015-04-11 75 2015-04-09 2015-04-08mart 2015-04-13 94 2015-04-11 2015-04-09neil 2015-05-10 12 1900-01-01 NULLneil 2015-06-12 80 2015-05-10 NULLtony 2015-01-02 15 1900-01-01 NULLtony 2015-01-04 29 2015-01-02 NULLtony 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 time2from t_window---------------------name orderdate cost time1 time2jack 2015-01-01 10 2015-01-01 2015-01-01jack 2015-01-05 46 2015-01-01 2015-01-05jack 2015-01-08 55 2015-01-01 2015-01-08jack 2015-02-03 23 2015-01-01 2015-02-03jack 2015-04-06 42 2015-01-01 2015-04-06mart 2015-04-08 62 2015-04-08 2015-04-08mart 2015-04-09 68 2015-04-08 2015-04-09mart 2015-04-11 75 2015-04-08 2015-04-11mart 2015-04-13 94 2015-04-08 2015-04-13neil 2015-05-10 12 2015-05-10 2015-05-10neil 2015-06-12 80 2015-05-10 2015-06-12tony 2015-01-02 15 2015-01-02 2015-01-02tony 2015-01-04 29 2015-01-02 2015-01-04tony 2015-01-07 50 2015-01-02 2015-01-07
SUM,AVG,MIN,MAX
用于实现分组内所有和连续累积的统计。
cookieid string,createtime string,pv INTcookie1 2015-04-10 1cookie1 2015-04-11 5cookie1 2015-04-12 7cookie1 2015-04-13 3cookie1 2015-04-14 2cookie1 2015-04-15 4cookie1 2015-04-16 4
SELECT cookieid,createtime,pv,SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS pv1, -- 默认为从起点到当前行SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS pv2, --从起点到当前行,结果同pv1SUM(pv) OVER(PARTITION BY cookieid) AS pv3, --分组内所有行SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS pv4, --当前行+往前3行SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) AS pv5, --当前行+往前3行+往后1行SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS pv6 ---当前行+往后所有行FROM lxw1234;cookieid createtime pv pv1 pv2 pv3 pv4 pv5 pv6-----------------------------------------------------------------------------cookie1 2015-04-10 1 1 1 26 1 6 26cookie1 2015-04-11 5 6 6 26 6 13 25cookie1 2015-04-12 7 13 13 26 13 16 20cookie1 2015-04-13 3 16 16 26 16 18 13cookie1 2015-04-14 2 18 18 26 17 21 10cookie1 2015-04-15 4 22 22 26 16 20 8cookie1 2015-04-16 4 26 26 26 13 13 4pv1: 分组内从起点到当前行的pv累积,如,11号的pv1=10号的pv+11号的pv, 12号=10号+11号+12号pv2: 同pv1pv3: 分组内(cookie1)所有的pv累加pv4: 分组内当前行+往前3行,如,11号=10号+11号, 12号=10号+11号+12号, 13号=10号+11号+12号+13号, 14号=11号+12号+13号+14号pv5: 分组内当前行+往前3行+往后1行,如,14号=11号+12号+13号+14号+15号=5+7+3+2+4=21pv6: 分组内当前行+往后所有行,如,13号=13号+14号+15号+16号=3+2+4+4=13,14号=14号+15号+16号=2+4+4=10
如果不指定ROWS BETWEEN,默认为从起点到当前行;
如果不指定ORDER BY,则将分组内所有值累加;
关键是理解ROWS BETWEEN含义,也叫做WINDOW子句:
PRECEDING:往前
FOLLOWING:往后
CURRENT ROW:当前行
UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING:表示到后面的终点
其他AVG,MIN,MAX,和SUM用法一样。
--AVGSELECT cookieid,createtime,pv,AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS pv1, -- 默认为从起点到当前行AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS pv2, --从起点到当前行,结果同pv1AVG(pv) OVER(PARTITION BY cookieid) AS pv3, --分组内所有行AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS pv4, --当前行+往前3行AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) AS pv5, --当前行+往前3行+往后1行AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS pv6 ---当前行+往后所有行FROM lxw1234;cookieid createtime pv pv1 pv2 pv3 pv4 pv5 pv6-----------------------------------------------------------------------------cookie1 2015-04-10 1 1.0 1.0 3.7142857142857144 1.0 3.0 3.7142857142857144cookie1 2015-04-11 5 3.0 3.0 3.7142857142857144 3.0 4.333333333333333 4.166666666666667cookie1 2015-04-12 7 4.333333333333333 4.333333333333333 3.7142857142857144 4.333333333333333 4.0 4.0cookie1 2015-04-13 3 4.0 4.0 3.7142857142857144 4.0 3.6 3.25cookie1 2015-04-14 2 3.6 3.6 3.7142857142857144 4.25 4.2 3.3333333333333335cookie1 2015-04-15 4 3.6666666666666665 3.6666666666666665 3.7142857142857144 4.0 4.0 4.0cookie1 2015-04-16 4 3.7142857142857144 3.7142857142857144 3.7142857142857144 3.25 3.25 4.0--AVGSELECT cookieid,createtime,pv,AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS pv1, -- 默认为从起点到当前行AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS pv2, --从起点到当前行,结果同pv1AVG(pv) OVER(PARTITION BY cookieid) AS pv3, --分组内所有行AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS pv4, --当前行+往前3行AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) AS pv5, --当前行+往前3行+往后1行AVG(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS pv6 ---当前行+往后所有行FROM lxw1234;cookieid createtime pv pv1 pv2 pv3 pv4 pv5 pv6-----------------------------------------------------------------------------cookie1 2015-04-10 1 1.0 1.0 3.7142857142857144 1.0 3.0 3.7142857142857144cookie1 2015-04-11 5 3.0 3.0 3.7142857142857144 3.0 4.333333333333333 4.166666666666667cookie1 2015-04-12 7 4.333333333333333 4.333333333333333 3.7142857142857144 4.333333333333333 4.0 4.0cookie1 2015-04-13 3 4.0 4.0 3.7142857142857144 4.0 3.6 3.25cookie1 2015-04-14 2 3.6 3.6 3.7142857142857144 4.25 4.2 3.3333333333333335cookie1 2015-04-15 4 3.6666666666666665 3.6666666666666665 3.7142857142857144 4.0 4.0 4.0cookie1 2015-04-16 4 3.7142857142857144 3.7142857142857144 3.7142857142857144 3.25 3.25 4.0--MAXSELECT cookieid,createtime,pv,MAX(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS pv1, -- 默认为从起点到当前行MAX(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS pv2, --从起点到当前行,结果同pv1MAX(pv) OVER(PARTITION BY cookieid) AS pv3, --分组内所有行MAX(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS pv4, --当前行+往前3行MAX(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) AS pv5, --当前行+往前3行+往后1行MAX(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS pv6 ---当前行+往后所有行FROM lxw1234;cookieid createtime pv pv1 pv2 pv3 pv4 pv5 pv6-----------------------------------------------------------------------------cookie1 2015-04-10 1 1 1 7 1 5 7cookie1 2015-04-11 5 5 5 7 5 7 7cookie1 2015-04-12 7 7 7 7 7 7 7cookie1 2015-04-13 3 7 7 7 7 7 4cookie1 2015-04-14 2 7 7 7 7 7 4cookie1 2015-04-15 4 7 7 7 7 7 4cookie1 2015-04-16 4 7 7 7 4 4 4
GROUPING SETS,GROUPING__ID,CUBE,ROLLUP
这几个分析函数通常用于OLAP中,不能累加,而且需要根据不同维度上钻和下钻的指标统计,比如,分小时、天、月的UV数。
month STRING,day STRING,cookieid STRING2015-03 2015-03-10 cookie12015-03 2015-03-10 cookie52015-03 2015-03-12 cookie72015-04 2015-04-12 cookie32015-04 2015-04-13 cookie22015-04 2015-04-13 cookie42015-04 2015-04-16 cookie42015-03 2015-03-10 cookie22015-03 2015-03-10 cookie32015-04 2015-04-12 cookie52015-04 2015-04-13 cookie62015-04 2015-04-15 cookie32015-04 2015-04-15 cookie22015-04 2015-04-16 cookie1
在一个GROUP BY查询中,根据不同的维度组合进行聚合,等价于将不同维度的GROUP BY结果集进行UNION ALL。其中的 GROUPING__ID,表示结果属于哪一个分组集合。
SELECTmonth,day,COUNT(DISTINCT cookieid) AS uv,GROUPING__IDFROM lxw1234GROUP BY month,dayGROUPING SETS (month,day)ORDER BY GROUPING__ID;month day uv GROUPING__ID------------------------------------------------2015-03 NULL 5 12015-04 NULL 6 1NULL 2015-03-10 4 2NULL 2015-03-12 1 2NULL 2015-04-12 2 2NULL 2015-04-13 3 2NULL 2015-04-15 2 2NULL 2015-04-16 2 2等价于SELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__ID FROM lxw1234 GROUP BY monthUNION ALLSELECT NULL,day,COUNT(DISTINCT cookieid) AS uv,2 AS GROUPING__ID FROM lxw1234 GROUP BY day
SELECTmonth,day,COUNT(DISTINCT cookieid) AS uv,GROUPING__IDFROM lxw1234GROUP BY month,dayGROUPING SETS (month,day,(month,day))ORDER BY GROUPING__ID;month day uv GROUPING__ID------------------------------------------------2015-03 NULL 5 12015-04 NULL 6 1NULL 2015-03-10 4 2NULL 2015-03-12 1 2NULL 2015-04-12 2 2NULL 2015-04-13 3 2NULL 2015-04-15 2 2NULL 2015-04-16 2 22015-03 2015-03-10 4 32015-03 2015-03-12 1 32015-04 2015-04-12 2 32015-04 2015-04-13 3 32015-04 2015-04-15 2 32015-04 2015-04-16 2 3等价于SELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__ID FROM lxw1234 GROUP BY monthUNION ALLSELECT NULL,day,COUNT(DISTINCT cookieid) AS uv,2 AS GROUPING__ID FROM lxw1234 GROUP BY dayUNION ALLSELECT month,day,COUNT(DISTINCT cookieid) AS uv,3 AS GROUPING__ID FROM lxw1234 GROUP BY month,day
CUBE
根据GROUP BY的维度的所有组合进行聚合。
SELECTmonth,day,COUNT(DISTINCT cookieid) AS uv,GROUPING__IDFROM lxw1234GROUP BY month,dayWITH CUBEORDER BY GROUPING__ID;month day uv GROUPING__ID--------------------------------------------NULL NULL 7 02015-03 NULL 5 12015-04 NULL 6 1NULL 2015-04-12 2 2NULL 2015-04-13 3 2NULL 2015-04-15 2 2NULL 2015-04-16 2 2NULL 2015-03-10 4 2NULL 2015-03-12 1 22015-03 2015-03-10 4 32015-03 2015-03-12 1 32015-04 2015-04-16 2 32015-04 2015-04-12 2 32015-04 2015-04-13 3 32015-04 2015-04-15 2 3等价于SELECT NULL,NULL,COUNT(DISTINCT cookieid) AS uv,0 AS GROUPING__ID FROM lxw1234UNION ALLSELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__ID FROM lxw1234 GROUP BY monthUNION ALLSELECT NULL,day,COUNT(DISTINCT cookieid) AS uv,2 AS GROUPING__ID FROM lxw1234 GROUP BY dayUNION ALLSELECT month,day,COUNT(DISTINCT cookieid) AS uv,3 AS GROUPING__ID FROM lxw1234 GROUP BY month,day
ROLLUP
是CUBE的子集,以最左侧的维度为主,从该维度进行层级聚合。
比如,以month维度进行层级聚合:SELECTmonth,day,COUNT(DISTINCT cookieid) AS uv,GROUPING__IDFROM lxw1234GROUP BY month,dayWITH ROLLUPORDER BY GROUPING__ID;month day uv GROUPING__ID---------------------------------------------------NULL NULL 7 02015-03 NULL 5 12015-04 NULL 6 12015-03 2015-03-10 4 32015-03 2015-03-12 1 32015-04 2015-04-12 2 32015-04 2015-04-13 3 32015-04 2015-04-15 2 32015-04 2015-04-16 2 3可以实现这样的上钻过程:月天的UV->月的UV->总UV
--把month和day调换顺序,则以day维度进行层级聚合:SELECTday,month,COUNT(DISTINCT cookieid) AS uv,GROUPING__IDFROM lxw1234GROUP BY day,monthWITH ROLLUPORDER BY GROUPING__ID;day month uv GROUPING__ID-------------------------------------------------------NULL NULL 7 02015-04-13 NULL 3 12015-03-12 NULL 1 12015-04-15 NULL 2 12015-03-10 NULL 4 12015-04-16 NULL 2 12015-04-12 NULL 2 12015-04-12 2015-04 2 32015-03-10 2015-03 4 32015-03-12 2015-03 1 32015-04-13 2015-04 3 32015-04-15 2015-04 2 32015-04-16 2015-04 2 3可以实现这样的上钻过程:天月的UV->天的UV->总UV(这里,根据天和月进行聚合,和根据天聚合结果一样,因为有父子关系,如果是其他维度组合的话,就会不一样)
这种函数,需要结合实际场景和数据去使用和研究,只看说明的话,很难理解。
官网的介绍: https://cwiki.apache.org/confluence/display/Hive/Enhanced+Aggregation%2C+Cube%2C+Grouping+and+Rollup
原文地址 http://lxw1234.com/archives/tag/hive-window-functions
参考:http://blog.csdn.net/xiepeifeng/article/details/42676567
http://www.cnblogs.com/skyEva/p/5730531.html
根据使用的目的,开窗函数可以分为两类:聚合开窗函数和排序开窗函数。
下面主要解析四种常用的排序开窗函数:
1、ROW_NUMBER() OVER();
2、RANK() OVER();
3、DENSE_RANK() OVER();
4、NTILE(n) OVER().
count() over(partition by … order by …):求分组后的总数。
max() over(partition by … order by …):求分组后的最大值。
min() over(partition by … order by …):求分组后的最小值。
avg() over(partition by … order by …):求分组后的平均值。
lag() over(partition by … order by …):取出前n行数据。  
lead() over(partition by … order by …):取出后n行数据。
ratio_to_report() over(partition by … order by …):Ratio_to_report() 括号中就是分子,over() 括号中就是分母。
percent_rank() over(partition by … order by …):
