DISTINCT与PARTITION BY对GROUPBY

时间:2013-12-04 12:13:20

标签: sql sql-server group-by distinct query-performance

我在我正在检查的应用程序中找到了一些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

使用第一种方法是否有任何好处(性能,可读性,编写查询的额外灵活性,可维护性等)?

3 个答案:

答案 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更强大。但要谨慎使用......一个简单的经验法则可能是:如果你可以使用分组计算它,那么,不要使用分析函数;)