name orderdate cost
jack 2017-01-01 10
jack 2017-02-03 23
jack 2017-01-05 46
jack 2017-04-06 42
jack 2017-01-08 55
mart 2017-04-08 62
mart 2017-04-09 68
mart 2017-04-11 75
mart 2017-04-13 94
使用如上數據。
先來直接感受一下 over中的partition by與group by。都以name字段分區
=======================gruop by=======================
select
name,
count(*)
from
overdemo
where
date_format(orderdate,'yyyy-MM')='2017-04'
group by
name;
--------結果---------
name _c1
jack 1
mart 4
=======================partition by========================
select
name,
count(*) over(partition by name)
from
overdemo
where
date_format(orderdate,'yyyy-MM')='2017-04';
--------結果---------
name count_window_0
jack 1
mart 4
mart 4
mart 4
mart 4
可以看到其實兩種方法的得到的結果的差別主要是partition by將所有符合過濾條件的mart都列了出來,所以,單單對於group by和over(partition by)來說,前者可以簡單地看作後者的去重版。
再進一層來說,over(partition by)是group by 的升級版。因爲over函數式在group by之後執行的,也就是說可以在group by 的基礎上,再進行一次partition by:先group by分組且去重,然後partition by結合聚合函數(count、sum等)進行分區運算
=====同時有group by name和over(partition by name)=====
select
name,
count(*) over(partition by name)
from
overdemo
where
date_format(orderdate,'yyyy-MM')='2017-04'
group by
name;
---------結果--------
name count_window_0
jack 1
mart 1
=====同時有group by name和over()=====over()無參數時結合聚合函數對全量數據進行運算
select
name,
count(*) over()
from
overdemo
where
date_format(orderdate,'yyyy-MM')='2017-04'
group by
name;
----------結果-------
name count_window_0
mart 2
jack 2
符合過濾條件的數據,經過group by之後得到的是去重的數據mart和jack:
①當over()無參數時,結合聚合函數count(*),對得到的數據進行計數,得到的結果就是2,並且會在mart和Jack後顯示2(因爲沒有進行partition by name,mart和Jack是在同一個分區的)
②當over(partition by name)之後,group by得到的數據會再次進行分區,分爲mart和jack,兩個分區中進行count(*)計算,都只有1個,所以在兩個分區中分別顯示爲1
此時,再解釋上面只使用over(partition by name)時,爲什麼mart會顯示4次,而且count(*)也是4。因爲符合過濾條件的mart有4條,都被partition by分到了一個分區,所以count(*)的結果就是4,而且over(partition by name)並不會去重,所以顯示了4次。
綜上,over(partition by)可以視爲group by的升級版:①會保留所有進入分區的數據,不去重(沒有數據損失);②在group by之後執行,可以進行更爲複雜個性化的操作