我在我正在检查的应用程序中找到了一些SQL查询:
SELECT DISTINCT
Company, Warehouse, Item,
SUM(quantity) OVER (PARTITION BY Company, Warehouse, Item) AS stock
我很确定这会产生与以下结果相同的结果:
SELECT
Company, Warehouse, Item,
SUM(quantity) AS stock
GROUP BY Company, Warehouse, Item
使用第一种方法是否有任何好处(性能,可读性,编写查询的额外灵活性,可维护性等)?
答案 0 :(得分:11)
获胜者:GROUP BY
对具有未编制索引的列的大型表进行的一些非常基本的测试表明,至少在我的情况下,这两个查询生成了完全不同的查询计划。 PARTITION BY
的那个明显变慢了。
GROUP BY
查询计划仅包括表扫描和聚合操作,而PARTITION BY
计划有两个嵌套循环自连接。 PARTITION BY
在第二次运行时耗时约2800毫秒,GROUP BY
只用了500毫秒。
获胜者:GROUP BY
根据评论者的观点,PARTITION BY
对大多数开发人员来说可读性较差,因此将来可能也难以维护。
获胜者:PARTITION BY
PARTITION BY
为您提供了更多选择分组列的灵活性。使用GROUP BY
,您只能为所有聚合列提供一组分组列。使用DISTINCT + PARTITION BY
,您可以在每个分区中使用不同的列。此外,在某些DBMS上,您可以从OVER
子句中的更多聚合/分析函数中进行选择。
答案 1 :(得分:2)
不需要使用sum()
作为over partition by
的分析函数。在任何意义上,我都不认为它们之间存在很大差异。在oracle中,分析功能比聚合功能要多得多。我认为ms-sql是一样的情况。例如,lag()
,lead()
,rank()
,dense rank()
等仅使用group by
更难实现。
当然,这个论点并不是为了捍卫第一个版本......
可能以前在结果集中有更多的计算字段,这些字段无法通过group by实现。
答案 2 :(得分:0)
虽然在查看列时,两个查询似乎都计算相同的内容,但它们实际上会生成完全不同的行集。
使用分析函数的第一个将为每个输入行输出一行。对于每个库存信息,它将返回一行,其中包含关联公司/仓库/物料的总数量。 (通过计算平均值对我来说更有意义,但谁知道...)
第二个只为每个公司/仓库/项目组合返回一行。
所以是的,在那个例子中,第一个查询看起来有点无用......除非你想要计算一些库存水平统计数据,比如公司/仓库/项目的总体数量当前库存比率(只是一个例子,不要'知道它是否有任何商业意义!)
分析函数是SQL中非常强大的机制,在某种意义上比group-by更强大。但要谨慎使用......一个简单的经验法则可能是:如果你可以使用分组计算它,那么,不要使用分析函数;)