网上对select 和group by的执行顺有不同的说法,很容易让人挠头,这里通过代码成功验证 : group by>select
正确的执行顺序:
from ..on .. join .. where .. group by .. having .. select .. distinct .. order by .. limit
案例:
1.数据原表:
2.执行sql:
select
dt,
user_id,
min(age) age,
rank() over(partition by user_id order by dt) rk
from
user_age
group by
dt,user_id;
3.执行结果:
4.执行顺序详解:
sql里有分区和分组两种操作,执行顺序不同会导致其结果也不同。其中分区操作为rank() over(partition by user_id order by dt) rk,分组操作为group by dt,user_id。
由于group by>select,所以先执行group by操作,再执行select操作。
具体执行步骤:
步骤1:执行group by dt,user_id,执行结果如下:
注:group by 后面有两个字段 dt,user_id,表示将这两个字段看成一个整体进行分组。
步骤2:执行select dt,user_id,min(age) age,rank() over(partition by user_id order by dt) rk
①依次执行dt,user_id,min(age) age由于min(age)这里出现聚合,所以会先对表进行聚合,聚合后的结果如下:
②接着执行rank() over(partition by user_id order by dt) rk 先根据user_id进行分区,再根据dt进行排序,结果如下:
由于select后没有其他操作了,所以该表为最终结果。
附:执行计划:
Map Operator Tree:
TableScan
alias: 表名 -- 相当于 from ...Filter Operator
predicate: where中的字段 -- 过滤where字段的条件Select Operator
expressions: select 中的字段 + 类型type -- select
outputColumnNames: 输出的字段 -- select
Group By Operator
aggregations: 聚合函数 sum(age)/count(age)等
keys: group by 中的字段 + 类型type
Reduce Output Operator
map端本地的reduceReduce Operator Tree:
Group By Operator
aggregations: sum(VALUE._col0) --reduce 聚合函数 对虚拟列
keys: KEY._col0 (type: string), KEY._col1 (type: string), KEY._col2 (type: string)
mode: mergepartial
outputColumnNames: _col0, _col1, _col2, _col3 --为临时结果字段按规则起的临时字段名
Select Operator
expressions: _col0 (type: string), _col1 (type: string), _col2 (type: string), _col3 (type: bigint) --select
outputColumnNames: _col0, _col1, _col2, _col3 -- 输出虚拟列(为临时结果字段按规则起的临时字段名)
File Output Operator
compressed: false