分组比较是看起来比较简单,但是写起来比较麻烦的问题,一般就是先进行两个不同分组计数、求和、求均值,然后两个均值作比较,这样就涉及表连接和判断,写的代码量就比其他问题多很多。它与连续问题、排名问题和累加问题不同的是,后面三个问题是数据行之间纵向产生关系,而这里是横向产生关系。
这类问题也是有一定套路的,下面用实际案例数据还原真实取数场景,帮助你在实战中理解如何实现分组比较取数的过程,总结思路。建议在电脑大屏阅读效果会更好。
需求:老板要求写一个查询语句,求出在每月每个经销商的平均销售金额与公司的平均销售金额的比较结果 (高 / 低 / 相同),这样以便于后续制定激励经销商的政策措施。你该如何写呢?
背景:数据来源于微软示例数据库,一家销售自行车制造公司的销售数据,分为网络销售FactInternetSales和经销商销售FactResellerSales两张表,其中网络销售订单数据60398行,经销商销售数据有60855行。此处我们简化问题,重点在问题的解决上,只用到FactResellerSaless表,表中有包含价格orderdate、resellerkey和salesamount在内的共计27个字段,每个日期存在多个订单情况。
分析:先分析需求看我们要取的是哪些字段,每月、每个经销商、经销商平均销售金额,公司、公司平均销售金额,比较结果,这里面公司字段值相同不需要取,经销商平均销售金额、公司平均销售金额,比较结果三个字段是原表没有的,因此需要新增计算字段。求平均需要用到avg函数,而判断条件,自然需要if语句或者case when语句(两种在功能上是相同的)。这一步是很多初学者可能都还没有形成的思维,一看到需求还无法迅速定位到要取什么数、用到什么函数。
角度一:简单查询是一张表取数,这里虽然原数据在一张表中,但是显然比较两个分组会产生两张临时表,所以就需要复合查询来解决。
角度二:聚合函数+复合查询
解法一 复合查询
下面是复合查询的代码:
with t1 as (select date_format(orderdate,"%Y-%m") as paydate,resellerkey,avg(salesamount) as avd
from FactResellerSales
group by date_format(orderdate,"%Y-%m"),resellerkey),
t2 as (select date_format(orderdate,"%Y-%m") as paydate,avg(salesamount) as ava
from FactResellerSales
group by date_format(orderdate,"%Y-%m"))
select paydate,resellerkey,t2.ava as allsa,t1.avd as allsd,
if(t1.avd<< span="">