GroupBy 用法的三重境界,面试终结者

用户头像
Hyun
关注
发布于: 2020 年 05 月 02 日
GroupBy 用法的三重境界,面试终结者



知乎上,有人说 SQL 很简单,24 小时就能入门;也有人说,数据库很简单,7周7数据库。



看着这些言论,我一度怀疑自己是不是又虚度了几年光阴。



接着翻翻,这些言论家洋洋洒洒罗列一堆的 SQL 语法,翻来覆去就是 SELECT *, 再一看,哦,原来作者是 XX 培训机构老师。一口老血封住我少见了世面的喉咙司令官。



为了显摆自己 SQL 知识的丰富,我经常在面试中加入 GroupBy 基础语法的考察,当然这类题并不会影响给候选者发 Offer. 那什么会影响呢,下回我们好好讲,这次只讲技术细节。



GroupBy,熟悉 SQL 的朋友都知道,是对集合数据做分组聚合运算。



举个最简单的例子,大概就长这样:



SELECT OrderMonth
,City
,Sum(OrderAmount) AS OrderAmount
FROM dbo.FctSalesMonthly 
GROUP BY OrderMonth ,City



用意很简单,统计每个月,每个城市的销售额。如果面试的时候,面试官给了你一道这样的题,说明面试的岗位相对初级一些,只要对维度有概念,这样的题,应该不能错。



接下来,我可能会为难你一下,除了统计每月每城市的销售额外,还要求统计每个月的总销售额,每个城市的总销售,以及总销售额,并且(这是古怪的需求)用一条 SQL 语句完成,结果集只能用一个



请注意最后一个要求,只能用一条SQL语句完成,结果集还只能有一个!



这时,解法可能就多了。有同学用动态SQL,有同学用CTE(不知道的同学谷歌里百度一下),有同学用子查询。很可能写了 n 多行的SQL。但事实上,只要在GroupBy上添加一行:



SELECT OrderMonth
,City
,Sum(OrderAmount) AS OrderAmount
FROM dbo.FctSalesMonthly 
GROUP BY   Cube(OrderMonth,City)
ORDER BY OrderMonth DESC,City



这样的题,其实对候选人也只是经验层面的考量。如果你碰巧对 SQL 特别感兴趣,又碰巧读过文档,那你肯定知道。但如果你不知道,也只能说明你还年轻。



如果上面两题都没难住你,那么我就会往第三个方向问了:



下面两段 SQL,同样求每月订单的最大销售额,哪个最优?



SELECT OrderMonth
,Max(OrderAmount) AS MaxAmount 
FROM FctSalesMonthly
GROUP BY OrderMonth
ORDER BY OrderMonth
SELECT Sales.OrderMonth
,RSL.Amount AS MaxAmount 
FROM FctSalesMonthly Sales 
CROSS APPLY(
SELECT TOP 1 Amt.OrderAmount            
FROM FctSalesMonthly Amt             
WHERE Amt.OrderMonth = Sales.OrderMonth            
)RSL 
ORDER BY Sales.OrderMonth 



我们都知道第二条SQL肯定不是最佳,同表扫描多次,性能就会很次。即使表数据完全缓存起来,排序依然耗CPU. 但第一条好在哪里?这就是重点,体现SQL的功底和经验的地方。



比如,你需要会看执行计划,需要熟知中间可能会发生的聚合, Hash Match, Stream Aggregate 以及其性能和适用条件。



Stream Aggregate 在全表或全索引扫描一遍的情况下,便可实现分组,配合索引能极快的加速排序。而Hash Match则是在混乱的分组场景下,得到快速分组。



如果上述例子中,OrderMonth 上并没有索引,你猜,执行计划会选择 Hash Match 还是 Stream Aggregate ? 



--完--



发布于: 2020 年 05 月 02 日 阅读数: 44
用户头像

Hyun

关注

关注数据库的互联网人 2013.04.12 加入

浸淫数据库行业十余年

评论

发布
暂无评论
GroupBy 用法的三重境界,面试终结者