Dav*_*rer 6 sql-server sql-server-2012
假设我们有一个Orders包含列的表order_id, total, discount
然后我们写一个类似于下面的查询
SELECT
COUNT(order_id) AS num_orders
, SUM(total) / COUNT(order_id) as avg_total
, SUM(discount) / COUNT(order_id) AS avg_discount
FROM Orders
Run Code Online (Sandbox Code Playgroud)
COUNT(order_id)Preserved的值是跨列还是重新计算(例如,是否有性能影响)?或者最好先确定计算值并在查询中使用这些值,例如:
DECLARE @order_count AS INT
SELECT
@order_count = COUNT(order_id)
FROM Orders
SELECT
@order_count AS num_orders
, SUM(total) / @order_count as avg_total
, SUM(discount) / @order_count AS avg_discount
FROM Orders
Run Code Online (Sandbox Code Playgroud)
请注意,在编写此问题时,我注意到由于AVG()支持SQL Server 2008 。但是,我继续了这个问题,并打算更一般地想了解 SQL Server 如何处理跨列的相同聚合,因为我有时会以其他形式遇到这个问题。
Mar*_*ith 10
SQL Server 只计算COUNT一次。您可以通过查看执行计划的属性来看到这一点
create table Orders(order_id int, total int, discount int)
SELECT
COUNT(order_id) AS num_orders
, SUM(total) / COUNT(order_id) as avg_total
, SUM(discount) / COUNT(order_id) AS avg_discount
FROM Orders
Run Code Online (Sandbox Code Playgroud)
流聚合 (1) 具有以下定义的值
[Expr1008] = Scalar Operator(COUNT([tempdb].[dbo].[Orders].[order_id])),
[Expr1009] = Scalar Operator(COUNT_BIG([tempdb].[dbo].[Orders].[total])),
[Expr1010] = Scalar Operator(SUM([tempdb].[dbo].[Orders].[total])),
[Expr1011] = Scalar Operator(COUNT_BIG([tempdb].[dbo].[Orders].[discount])),
[Expr1012] = Scalar Operator(SUM([tempdb].[dbo].[Orders].[discount]))
Run Code Online (Sandbox Code Playgroud)
Expr1008是COUNT您询问的计算。
COUNT其他两列还有一些其他聚合。这些是必需的,因为SUM(total)(例如) if COUNT(total)is的正确结果0应该是NULL。
这由沿 (2) 的下一个计算标量执行。这也将COUNT结果 ( Expr1008) 从转换bigint为int并标记为Expr1003
[Expr1003] = Scalar Operator(CONVERT_IMPLICIT(int,[Expr1008],0)),
[Expr1004] = Scalar Operator(CASE WHEN [Expr1009]=(0) THEN NULL ELSE [Expr1010] END),
[Expr1005] = Scalar Operator(CASE WHEN [Expr1011]=(0) THEN NULL ELSE [Expr1012] END)
Run Code Online (Sandbox Code Playgroud)
最后最左边的计算标量 (3) 用于Expr1003除法运算......
[Expr1006] = Scalar Operator([Expr1004]/[Expr1003]),
[Expr1007] = Scalar Operator([Expr1005]/[Expr1003])
Run Code Online (Sandbox Code Playgroud)
...并输出列Expr1003, Expr1006, Expr1007作为最终结果
PS:AVG支持的时间比 SQL Server 2008 长得多。我想它可能一开始就可用。但是,NULL无论如何,它与您在s存在的情况下重写的语义不同。
我假设order_id是主键,因此不可为空,但对于具有 10 个订单和两个NOT NULL total值的表2,4然后AVG(total)将是3但SUM(total) / COUNT(order_id)将是0.6(或0一旦考虑整数除法)。
| 归档时间: |
|
| 查看次数: |
506 次 |
| 最近记录: |