語法:
分析函數 over(partition by 列名 order by 列名 rows between 開始位置 and 結束位置)
常用分析函數:
-
聚合類
avg()、sum()、max()、min() -
排名類
row_number() 按照值排序時產生一個自增編號,不會重復
rank() 按照值排序時產生一個自增編號,值相等時會重復,會產生空位
dense_rank() 按照值排序時產生一個自增編號,值相等時會重復,不會產生空位 -
其他類
lag(列名,往前的行數,[行數為null時的默認值,不指定為null])
lead(列名,往后的行數,[行數為null時的默認值,不指定為null])
ntile(n) 把有序分區中的行分發到指定數據的組中,各個組有編號,編號從1開始,對於每一行,ntile返回此行所屬的組的編號
注意點:
- over()函數中的分區、排序、指定窗口范圍可組合使用也可以不指定,根據不同的業務需求結合使用
- over()函數中如果不指定分區,窗口大小是針對查詢產生的所有數據,如果指定了分區,窗口大小是針對每個分區的數據
over()函數中的窗口范圍說明:
current row:當前行
unbounded:起點,unbounded preceding 表示從前面的起點, unbounded following表示到后面的終點
n preceding :往前n行數據
n following:往后n行數據
實戰案例1:
原始數據(用戶購買明細數據)
name,orderdate,cost
jack,2017-01-01,10
tony,2017-01-02,15
jack,2017-02-03,23
tony,2017-01-04,29
jack,2017-01-05,46
jack,2017-04-06,42
tony,2017-01-07,50
jack,2017-01-08,55
mart,2017-04-08,62
mart,2017-04-09,68
neil,2017-05-10,12
mart,2017-04-11,75
neil,2017-06-12,80
mart,2017-04-13,94
建表加載數據
vi business.txt
create table business
(
name string,
orderdate string,
cost int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
load data local inpath "/opt/module/data/business.txt" into table business;
需求
(1)查詢在2017年4月份購買過的顧客及總人數
分析:按照日期過濾、分組count求總人數(分組為什么不是用group by?自己思考)
select
name,
orderdate,
cost,
count(*) over() total_people
from
business
where date_format(orderdate,'yyyy-MM')='2017-04';
(2)查詢顧客的購買明細及月購買總額
分析:按照顧客分組、sum購買金額
select
name,
orderdate,
cost,
sum(cost) over(partition by name) total_amount
from
business;
(3)上述的場景,要將cost按照日期進行累加
分析:按照顧客分組、日期升序排序、組內每條數據將之前的金額累加
select
name,
orderdate,
cost,
sum(cost) over(partition by name order by orderdate rows between unbounded preceding and current row) cumulative_amount
from
business;
(4)查詢顧客上次的購買時間
分析:查詢出明細數據同時獲取上一條數據的購買時間(肯定需要按照顧客分組、時間升序排序)
select
name,
orderdate,
cost,
lag(orderdate,1) over(partition by name order by orderdate) last_date
from
business;
(5)查詢前20%時間的訂單信息
分析:按照日期升序排序、取前20%的數據
select
*
from
(
select
name,
orderdate,
cost,
ntile(5) over(order by orderdate) sortgroup_num
from
business
) t
where t.sortgroup_num=1;
實戰案例2:
原始數據(學生成績信息)
name subject score
孫悟空 語文 87
孫悟空 數學 95
孫悟空 英語 68
大海 語文 94
大海 數學 56
大海 英語 84
宋宋 語文 64
宋宋 數學 86
宋宋 英語 84
婷婷 語文 65
婷婷 數學 85
婷婷 英語 78
建表加載數據
vi score.txt
create table score
(
name string,
subject string,
score int
) row format delimited fields terminated by "\t";
load data local inpath '/opt/module/data/score.txt' into table score;
需求:
(1)每門學科學生成績排名(是否並列排名、空位排名三種實現)
分析:學科分組、成績降序排序、按照成績排名
select
name,
subject,
score,
rank() over(partition by subject order by score desc) rp,
dense_rank() over(partition by subject order by score desc) drp,
row_number() over(partition by subject order by score desc) rmp
from
score;
(2)每門學科成績排名top n的學生
select
*
from
(
select
name,
subject,
score,
row_number() over(partition by subject order by score desc) rmp
from score
) t
where t.rmp<=3;