SQL SUM查询返回结果中的重复行

时间:2015-01-24 00:09:37

标签: sql sql-server

我有一张桌子' order'包含摘要订单信息和表' orderItem'与订单的每个项目。

我的问题是:选择列的总和' orderQTY'来自'订单'如果我加入orderItem表,我得到一个不正确的总数。

下面的第一个查询给出了正确的总数。 但是,只要我将连接添加到orderItem,总和结果就会错误地复制' orderqty'每个orderitem记录的列。

  

nb:我知道下面没有使用联接,也没有必要。   我已经删除了引用联接表的条款以简化   问题

--RETURNS Correct value
select sum(o.orderqty) 
from [order] o 

--RETURNS the sum containing duplicates of o.orderqty
select sum(o.orderqty)
from [order] o  
join OrderItem oi on o.Id = oi.OrderId

- 补充说明:----
我想要总结列' orderqty'来自表' order'加入orderItem时,例如:

每个订单会有多个orderItem,但我只想显示每个订单只计算一次订单表中的orderqty。

select sum(o.ordertotal)
from [order] o with(NOLOCK)
join OrderItem oi on o.Id = oi.OrderId
where oi.mycolumn = 1

或者我需要做类似的事情:

select sum(o.ordertotal)
from [order] o with(NOLOCK)
where o.id in (select orderid from orderitem where x = y)

4 个答案:

答案 0 :(得分:4)

它会返回不同的结果,因为join会将行数或过滤行数相乘,这两行都会影响总和。目前还不清楚你真正想做什么。如果您只想要具有订单行的订单数量的总和,则使用exists:

select sum(o.orderqty)
from [order] o  
where exists (select 1
              from OrderItem oi 
              where o.Id = oi.OrderId
             );

答案 1 :(得分:1)

您可以使用row_number函数对每个分组(在本例中为order.id)求和一次:

select sum(orderqty)
from (
    select
        case row_number() over(partition by o.Id order by o.id)
            when 1 then orderqty
            else 0
        end as orderqty
    from [order] o  
        join OrderItem oi on o.Id = oi.OrderId
    ) o

答案 2 :(得分:0)

加入工作以创建组合来自多个表的数据的结果集。然后,SQL在此组合结果集上运行聚合函数和where子句。所以想象你有2个订单,1个单项,1个2项:

// Order table
OrderId   OrderQty
1         5
2         3

// OrderItem table
OrderId   ItemId
1         1
2         1
2         2

您的加入会给您以下结果:

OrderId   OrderQty   OrderId   ItemId
1         5          1         1
2         3          2         1
2         3          2         2

所以,当你SUM(OrderQty)时,我认为你想要的是11而不是8。在这种情况下,链接到另一个表是没有意义的......

答案 3 :(得分:0)

FROM子句(就像它一样)计算中间table

SELECT子句表达式

sum(o.orderqty)

并不表示"表orderqty"的o列的总和。它表示" FROM子句"生成的中间表的o.orderqty列的总和。

以下是示例表:

// [order]
Id  orderqty
 1   33
 2   66

// OrderItem
OrderId  ItemId
 2        7
 1        8
 1        9

这是第二个查询:

select sum(o.orderqty)
from [order] o  
join OrderItem oi on o.Id = oi.OrderId

首先,FROM计算一个"交叉产品"它具有您加入的表中的一行的所有可能组合。所以它的每一行都有一个来自每个表的子行。每个子行都有列名,如源表列名,但源表名或别名前缀为点。 (如果没有歧义,您不需要提及前缀和点来引用FROM子句表列。)

// [order] o join OrderItem oi
o.Id  o.orderqty  oi.OrderId  oi.ItemId
  1     33           2           7
  1     33           1           8
  1     33           1           9
  2     66           2           7
  2     66           1           8
  2     66           1           9

然后删除ON和WHERE失败的行:

// [order] o join OrderItem oi on o.Id = oi.OrderId
o.Id  o.orderqty  oi.OrderId  oi.ItemId
  1     33           1           8
  1     33           1           9
  2     66           2           7

这是SELECT使用的第二个查询FROM中间表。这是SELECT使用的第一个查询的FROM中间表:

// [order] o
o.Id  o.orderqty
  1     33
  2     66

因此第二个查询的SUM(o.orderqty)是33 + 33 + 66,而第一个查询是33 + 66。由于对于[order]的FROM子句表需要SUM,因此需要第一个查询。

(我们也可以在逐个连接的基础上对此进行描述,这使我们可以解释LEFT JOIN与INNER JOIN,CROSS JOIN和","以及USING和NATURAL如何制作差。)

重新更新:您尚未从查询中解释想要返回的行。也许你想要:

select oi.Id, oi.orderId, o.orderqty, ...
from [order] o  
join OrderItem oi on o.Id = oi.OrderId

select ..., (select sum(orderqty) from [order]) as totalqty, ...