1.什麼是窗口函數
在明白窗口函數的用途之前,我們先稍微提一下聚合函數,比如sum, count等常用的聚合函數,作用是將一列中多行的值合併爲一行。與之對應的是,窗口函數完成的功能是本行內運算,從而多行的運算結果,即每一行的結果對應的多行的結果。一般窗口函數的語法爲
function() over (partition by column1, column2 order by column3)
2.窗口函數的類型
1.聚合型,像sum,count,avg等操作。
2.分析型,像rank, row_number, dense_rank等常見的排序窗口函數。
3.取值型窗口函數, lag, lead等。
3.例子
3.1 取分組以後的最大值
select * from
(
select *,ROW_NUMBER() OVER(PARTITION BY idtype ORDER BY id DESC) as num
from tablexxx
) t
where t.num = 1
上面的代碼,先按照idtype進行分組partition,然後取每個分組中最大的那個id。
3.2 按某個字段分組以後將另外的字段聚合
select collect_set(b) over(distribute by a order by c) from tablexxx
按字段a分組,按字段c排序,然後將字段b聚合在一起。如果是collect_list表示字段不去重,collect_set表示字段去重。
如果需要對字段b裏的內容進行排序,可以用sort_array。
select sort_array(collect_set(b) over(distribute by a)) from tablexxx
3.3 與group by做對比
假設有以下數據
zs classA 80
ls classB 83
ww classA 88
xl classC 92
wl classB 79
lu classC 85
字段名分別爲name, grade, score,表名爲table_test_data。現在想獲取每個grade的最大score,我們可以這麼寫
select grade, max(score) from table_test_data where date=20200409 group by grade
當然,我們還可以用窗口函數寫
select grade, score from (select *, row_number() over (partition by grade order by score desc) as num from browser.table_test_data where date=20200409)t where t.num = 1;
上面兩個語句跑出來的結果相同
grade score
classA 88
classB 83
classC 92
當然直接用group by比窗口函數要簡單很多。但是如果我們還想獲取name咋辦?
這個時候group by就無能爲力了,窗口函數可以。
select name, grade, score from (select *, row_number() over (partition by grade order by score desc) as num from browser.table_test_dta where date=20200409)t where t.num = 1;
結果爲
name grade score
ww classA 88
ls classB 83
xl classC 92
總結一下就是
如果要select出不在group by語句中的字段,而且該字段不在聚合函數裏,則應該使用row_number() over(partition by),如果需要select的字段全在group by中,則可以直接使用group by語句。