当我们错误的使用分组函数之后,mysql会报错,提示“ Invalid use of group function”,这就是今天要说的问题:where后面不能直接跟分组函数。
为什么他们不能跟在where后面?
这几个函数在使用时一般都和group by联合使用,原理是先分组再进行函数计算。当然我们在平常使用时,有这种情况。
select max(age) from t_student
这个sql语句中并没有group by,但还是可以使用分组函数max。这是因为当sql语句种没有手动使用group by时,那整个调用的表默认是一个分组。max函数是在这个大分组中取的最大值。所以我们就可以知道,应该是先分组,再调用分组函数,这样的逻辑。
接下来我们了解下sql语句执行的顺序
例:从学生表t_student中筛选出3年级年龄最大的女孩儿们,结果按照学号id升序
select max(age) from t_student where grade = 3 group by sex having sex = girl order by studentID asc
第一步:from 选择表
第二步:where 筛选条件,筛选对象–行( row 数据记录 )
第三步:group by 将筛选出来的数据进行分组
第四步:having 筛选条件,筛选对象–组
第五步:select 选取最后的结果
第六步:order by 将结果按照特定顺序排列
从上面的执行顺序我们又知道了先执行where,后group by分组,分组完之后才能使用分组函数。
所以where后面的筛选条件出现了分组函数那就会报错。还没有进行分组呢,不能使用分组函数。
当我们遇到这种情况时,就要改变思路,用子查询即可,where后面跟一个子查询就迎刃而解了。
select 、from、where、group by、having、order by
select :指定查看结果集中的那个列或列的计算结果
from :从哪张表查询数据
where :筛选过滤条件
group by :将上面过滤出的数据,进行分组
having :对上面已经分组的数据进行过滤的条件
order by :对查询到的结果进行排序。升序:asc,降序:desc
书写顺序:
select > from > where > group by > having > order by
其中select
和from
关键字是必不可少的,其他关键字是可选的。
执行顺序:
from > where > group by > having > select > order by
select 之前:负责检索数据。
select和order by : 负责设置查看规则。
窗口函数是什么鬼?
窗口函数指定了函数工作的数据窗口大小(当前行的上下多少行),这个数据窗口大小可能会随着行的变化而变化。
窗口函数和聚合函数区别?
窗口函数对于每个组返回多行,组内每一行对应返回一行值。
聚合函数对于每个组只返回一行。
1、字符串操作函数:split、concat、ifnull、cast
2、聚合函数 : hive适用于分析,所以常用。
3、时间函数 : 数仓的特征随时间变化而变化,所以时间也特别多
4、窗口函数:sum() over() 、 count() over() 、 排名函数
接下来,着重讲解hive的窗口函数。
sum(col) over() : 分组对col累计求和,over() 中的语法如下
count(col) over() : 分组对col累计,over() 中的语法如下
min(col) over() : 分组对col求最小
max(col) over() : 分组求col的最大值
avg(col) over() : 分组求col列的平均值
first_value(col) over() : 某分区排序后的第一个col值
last_value(col) over() : 某分区排序后的最后一个col值
lag(col,n,DEFAULT) : 统计往前n行的col值,n可选,默认为1,DEFAULT当往上第n行为NULL时候,取默认值,如不指定,则为NULL
lead(col,n,DEFAULT) : 统计往后n行的col值,n可选,默认为1,DEFAULT当往下第n行为NULL时候,取默认值,如不指定,则为NULL
ntile(n) : 用于将分组数据按照顺序切分成n片,返回当前切片值。注意:n必须为int类型。
排名函数:
row_number() over() : 排名函数,不会重复,适合于生成主键或者不并列排名
rank() over() : 排名函数,有并列名次,名次不连续。如:1,1,3
dense_rank() over() : 排名函数,有并列名次,名次连续。如:1,1,2
over(分组 排序 窗口) 中的order by后的语法:
1、物理窗口(真实往上下移动多少行rows between):
CURRENT ROW | UNBOUNDED PRECEDING | [num] PRECEDING AND UNBOUNDED FOLLOWING | [num] FOLLOWING| CURRENT ROW
如: over(partition by col order by rows between 1 preceding and 1 fllowing)
2、 逻辑窗口(满足条件上下多少行):(金融行业、保险行业、p2p等)
range between [num] PRECEDING AND [num] FOLLOWING
如: over(partition by col order by range between 5 preceding and 5 fllowing)
注意:窗口函数一般不和group by搭配使用。
应用: 某天某产品的累计销售额。
物理窗口:
求多维度累计(累计退款金额、累计交易额、累计订单数量)
逻辑窗口:
范围累计环比情况、某值上下加减。
数据:
userid,month,visits
A,2015‐01,5
A,2015‐01,15
B,2015‐01,5
A,2015‐01,8
B,2015‐01,25
A,2015‐01,5
A,2015‐02,4
A,2015‐02,6
B,2015‐02,10
B,2015‐02,5
A,2015‐03,16
A,2015‐03,22
B,2015‐03,23
B,2015‐03,10
B,2015‐03,1
每个用户截止到每月为止的最大单月访问次数和累计到该月的总访问次数,结果数据格式如下:
答案:
-- 建表语句
c*reate table visits(
userid string,
month string,
visits int
)
row format delimited fields terminated by ','
;
-- 装载数据语句
load data local inpath '/home/visits' into table visits;
-- 查询语句
select
t.userid,
t.month,
max(visits) over(distribute by t.userid sort by t.month) max_visits,
sum(visits) over(distribute by t.userid sort by t.month) total_visits,
t.visits
from (select
vs.userid,
vs.month,
sum(visits) visits
from visits vs
group by vs.userid,vs.month) t
;
查询结果:
OK
A 2015‐01 33 33 33
A 2015‐02 33 43 10
A 2015‐03 38 81 38
B 2015‐01 30 30 30
B 2015‐02 30 45 15
B 2015‐03 34 79 34
注意:
1、月份转换成成时间戳更好
2、子查询不会限制性能,相反更好。
hive的窗口函数咱们就介绍到这儿啦。