Pet*_*ter 5 sql sql-server group-by
假设我有这个查询:
SELECT CompanyId, COUNT(*) as Total
FROM Customer
GROUP BY CompanyId
HAVING COUNT(*) > 100
Run Code Online (Sandbox Code Playgroud)
COUNT(*)我的查询中有两次。这是否意味着COUNT执行了两次?
这是一个简单的示例,但是当我进行更复杂的计算(例如SUM(Weight) / COUNT(*))时,我担心它可能会影响性能。或者任何性能影响都可以忽略不计?
我正在使用 MS SQL 2012,并且无法执行HAVING Total > 100.
如果您对查询的幕后处理方式非常感兴趣,请熟悉执行计划以及如何阅读它们。以下所有内容都是使用这些内容通过实验建立的。
聚合不会计算多次,但涉及聚合的表达式却会计算多次。考虑:
SELECT CompanyId, SUM(Weight) / COUNT(*)
FROM Customer
GROUP BY CompanyId
HAVING SUM(Weight) / COUNT(*) > 100
Run Code Online (Sandbox Code Playgroud)
SUM(Weight)并且COUNT(*)只会计算一次,但除法将执行两次(一次在过滤时,一次在选择时)。当然,这对性能没有可衡量的影响——关键是它最大限度地减少了必须检查所有数据的次数。
这意味着即使您的列表HAVING与您的列表完全不同SELECT,该表仍然只会被扫描一次并聚合一次:
SELECT CompanyId, MAX(Weight), MIN(Weight), COUNT(*) as Total
FROM Customer
GROUP BY CompanyId
HAVING MAX(Weight) > 2 * MIN(Weight) AND AVG(Weight) > 0.5
Run Code Online (Sandbox Code Playgroud)
这里有四个聚合:MAX(Weight)、MIN(Weight)和。1优化器将一次性计算所有这些,按 分组,应用过滤器,然后选择所需的结果。2AVG(Weight)COUNT(*)CompanyIdHAVING
免责声明:与有关优化器功能的所有声明一样,所有这些都可能在 SQL Server 的任何版本中发生更改,并且可能会因跟踪标志、统计信息、索引和特定查询的具体情况而异。上述情况对于 SQL Server 2012 和 2016 来说是正确的,至少对于两个特定的数据库来说是这样,其中索引不起作用。
AVG实际上它本身并不是一个聚合体;在内部,优化器将其扩展为SUM / COUNT(*),并进行检查以防止被零除。所以聚合实际上是MAX、MIN、SUM和COUNT。