sql 聚合技巧总汇

参考资料:《Effective SQL 编写高质量sql语句的61个有效方法》进度:3/61

聚合使用说明

1 GROUP BY 后面跟随的字段不可以用别名

2 GROUP BY 后select字段必须是GROUP BY可以表达的

可以:select A+B from T group by A,B
可以:select A+B+constant from T group by A+B
不可以:select A,B from T group by A+B
不可以:select A+constant+B from T group by A+B

3 聚合函数
count/sum/avg/min/max/var_pop 总体方差/var_samp 样本方差/stddev-pop 总体标准差/stddev_samp 样本标准差 (总体还是样本是看平均时候除以N还是N-1,样本)

4 在使用GROUP BY之前应该用where把尽可能多的数据过滤掉,减少聚合过程中需要计算的内容

5 HAVING用于筛选聚合后的结果,使用时不能用select 中写的字段别名,需要把聚合的表达式重新写一遍

6 sql-92标准中需要把所有列都加在group by 后面,sql-99标准可以支持不用加在后面(mysql支持,其他支持的很少)
ps:听说sql-99有一千页,非常大块头。

7 建议不要把相关列放在groupby里,建议放在子查询里。提高聚合效率,同时也便于他人理解sql

select a.studentID,b.studentName,b.studentAge,sum(a.score)
from T1 as a 
group by a.studentID
left join T2 as b on a.studentID=b.studentID

其他聚合方式

原始表格:

维度1维度2指标
Aa9
Ab10
Ba4

ROLLUP 上卷

维度1维度2指标
Aa9
Ab10
Ba4
Anull19
Bnull4
nullnull23

CUBE

维度1维度2指标
Aa9
Ab10
Ba4
Anull19
Bnull4
nulla13
nullb10
nullnull23

GROUPING SET

维度1维度2指标
Anull19
Bnull4
nulla13
nullb10
nullnull23

使用方式

select 维度1,维度2,sum(指标)
from table
group by ROLLUP (维度1,维度2)/CUBE(维度1,维度2)/GROUPING SET ((维度1),(维度2),())
  • mysql 不支持rollup和cube

使用HAVING的四个例题

第一题

找到平均缴获时间超过所有供应商的平均缴获时间的供应商(挑选低效率的供应商)
数据源表Orders结构:OrderID订单,VendorID供应商,OrderDate订单时间,DeliveryDate缴获时间

select  VendorID,avg(datadiff(OrderDate-DeliveryDate))as DeliveryTime
from Orders
where DeliveryDate is not Null
and OrderDate between A and B
group by VendorID
having sum(datadiff(OrderTime-DeliveryTime))< (
select avg(datadiff(OrderDate-DeliveryDate)) from Orders
where DeliveryDate is not Null and OrderDate between A and B
)

第二题

列出在一定时间内的总销售额大于某一品类别下的所有产品的平均销售额的产品(安好啊类别查找畅销产品)
数据源表Orders结构:OrderID订单,CategoryID品类,ProductID产品,Price销售价,OrderDate 日期

select  CategoryID,ProductID,sum(Price)
from Orders AS O1
where OrderDate between A and B
group by CategoryID,ProductID
having sum(Price)>(
	select  avg(sumPrice)
	from(
		select CategoryID,ProductID,sum(Price) as sumPrice 
		from Orders AS O2
		where OrderDate between A and B 
		and O2.CategoryID=O1.CategoryID
		group by CategoryID,ProductID)
	group by CategoryID
)
  • 可以用CTE 可以作为临时表,简化代码。注意,使用CTE允许你定义一次复杂的链接和日期过滤,然后在外部子查询中用。

第三题

显示在任何一天订单总额超过1000美元的客户(列出每天的大额消费客户)
数据源表Orders结构:OrderID订单,CustomerID客户,Price消费金额,OrderDate 日期

select  OrderDate,CustomID,sum(Price)
from Orders 
where OrderDate between A and B
group by OrderDate,CustomerID
having sum(Price)>1000

第四题

计算最后一个季度单个订单的销售百分比
数据源表Orders结构:OrderID订单,ProductID产品,Price消费金额,OrderDate 日期

select  
	OrderID,
	sum(Price)(select sum(Price)from Orders where OrderDate between A and B)
from Orders 
where OrderDate between A and B
group by OrderID

存在疑问的点:
?为什么不建议用select distinct
A:因为distinct效率比group by低
? hive,sparksql,presto用的是sql92的标准么?
?什么情况下可以用CTE?
?什么范围的sql引擎可以用?
?CTE只能用一次还是可以使用多次?
? 第二题为什么这样写就可以对齐

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值