Hive学习笔记 为什么group by不能使用别名?
Posted 赤兔在云端
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive学习笔记 为什么group by不能使用别名?相关的知识,希望对你有一定的参考价值。
赤兔 | 学习笔记
注意SQL语句的执行顺序
问题来自于类似如下的场景:数据库中的每行代表一个用户的购买记录,每列是用户和购买的属性,例如性别、购买时间等,其中的一个字段代表的是消费者购买金额。现在要求按照消费金额分档,并统计各档位的消费者数量。比如我们按0元-500元、500元-1000元和1000元+将用户分成三组,并统计出各组的用户数量。
错误的方法:当我遇到这个问题,首先想到的是生成一个新列,并按新列分组。方法是使用case when语句将用户分组,然后给这列起一个别名,比如就叫classifying好了,再用group by classifying,就可以统计出各组的用户数量了。但是当执行的时候,会报语句错误:classifying这列不存在。
给查询的列起别名是很常用的方法,为什么这里却不行了呢?
1.可能group by不支持新生成的列的别名
2.可能group by后面就是不能使用别名
为了验证可能的原因,我用数据库原有的字段进行分组尝试,结果一旦使用了别名就会报错,而用原有列名则能正常查询。这就很奇怪了,为什么order by可以使用别名,但是group by不可以呢?按照人的习惯,使用别名更加方便才对,为什么不这样设计呢?
反复思索后,我突然想到:select后面的列其实是查询结果,而group by是查询的条件,order by是基于结果之后的排序,有没有可能程序是按照一定的顺序执行SQL语句的呢?如果是这样,where后面应该也不能使用别名,通过试验果真如此。在网上搜索了一些问题之后,终于找到了满意的解释,一般来说,查询的执行顺序是:
不同的数据库,还会有其它语句的优先级需要考虑,比如START WITH、CONNECT BY等,因为在hive中用不到就没有进一步研究了。
回到最初的问题,既然无法使用别名,那么如何按照我们设想的方式分组呢?答案是只能麻烦一些,把我们查询的case when语句放到group by后面,例如:
group by这样使用,让我想起曾在课堂上见过的一道面试题:
这里其实就是group by后面需要添加条件的情况,参考答案如下(经本人测试有些小问题):
(小问题是,select后面的case when需要和group by的条件保持一致,本例中group by用<9000和<20进行分组,那么需要在select里先写salary<9000以及age<20的条件,否则会报错。即 case when salary<9000 then '薪资小于9000' else '薪资大于9000' end as '薪资')
这里可以发现group by的有意思之处,group by不仅可以按照原有字段分组,还可以根据新的条件分组,只不过在二分组的情况下语句简单,而多分组的语句要复杂一些。二分组其实也是比较有用的,比如有的时候可以结合LEFT JOIN和<some_list> IS NULL来进行分组,就不用写更多的case when语句了(外连接后关键字段会产生空值,巧妙的利用可以解决一些本来复杂的查询问题)。
此外,需要注意的是,使用group by后,select的字段必须是出现在group by之后的字段,或者使用聚合函数,这个过程可以使用excel的数据透视表来理解。简单说就是,想要显示未经分组的字段记录,是不符合逻辑的(比如按年龄分组却要显示性别是不行的,必须把性别也加到分组条件中)。
总结一下:
1.SQL语句的执行是有先后顺序的,因此大部分数据库,WHERE和GROUP BY后面不能使用别名,但是ORDER BY可以使用别名。
2.GROUP BY后面的列,可以是复杂的分组判断,用CASE WHEN语句实现;但如果是二分组问题就比较简单,只写一个条件即可,不过要注意和SELECT的条件一致。
3.使用GROUP BY,SELECT后面的字段必须是GROUP BY后的字段或者聚合函数,不能查询在GROUP BY后面未出现的列。
以上是关于Hive学习笔记 为什么group by不能使用别名?的主要内容,如果未能解决你的问题,请参考以下文章
hive distribute by 和group by 的区别
SQL (Hive):在使用 GROUP BY 进行聚合时使用窗口函数