聚合函数SUM返回不同的值

时间:2013-02-05 15:19:37

标签: sql sql-server sum aggregate-functions

我有以下示例数据库架构

http://i.stack.imgur.com/EKNxY.jpg

enter image description here

我想:
A)所有销售,按用户分组。
B)折扣,按用户分组。

我正在使用以下查询:
FOR A:

    SELECT u.UserID, u.UserName, Sum(d.Quantity * i.Price) AS 'Sales'
FROM OrderDetails d
INNER JOIN Orders o ON o.OrderID = d.OrderID
INNER JOIN Item i ON i.ItemID = d.ItemID
INNER JOIN [User] u ON u.UserID = o.UserID
GROUP BY u.UserID, u.UserName

结果:
UserID用户名销售
1 Mobeen 11060
2收银员25960

FOR B:

    SELECT u.UserID, u.UserName, Sum(r.DiscountAmount) AS Discounts
FROM Receipt r
INNER JOIN Orders o ON o.OrderID = r.OrderID
INNER JOIN [User] u ON u.UserID = o.UserID
GROUP BY u.UserID, u.UserName

结果:
UserID用户名折扣
1 Mobeen 50
2收银员310

然后我决定将两个查询结合起来,但现在问题是我得到了不同的结果。 查询如下:

    SELECT u.UserID,
    u.UserName,
    Sum(d.Quantity * i.Price) AS 'Sales',
    Sum(r.DiscountAmount) AS 'Discounts'
FROM OrderDetails d
INNER JOIN Orders o ON o.OrderID = d.OrderID
INNER JOIN Item i ON i.ItemID = d.ItemID
INNER JOIN [User] u ON u.UserID = o.UserID
INNER JOIN Receipt r ON r.OrderID = o.OrderID
GROUP BY u.UserID, u.UserName

结果:
UserID用户名销售折扣
1 Mobeen 2270 50
2收银员25760 430

2 个答案:

答案 0 :(得分:4)

问题是你在多个方面进行求和。如果要组合它们,请使用子查询:

select s.userID, s.userName, s.Sales, d.Discounts
from (SELECT u.UserID, u.UserName, Sum(d.Quantity * i.Price) AS 'Sales'
      FROM OrderDetails d
           INNER JOIN Orders o ON o.OrderID = d.OrderID
           INNER JOIN Item i ON i.ItemID = d.ItemID
           INNER JOIN [User] u ON u.UserID = o.UserID
           GROUP BY u.UserID, u.UserName
     ) s join
     (SELECT u.UserID, u.UserName, Sum(r.DiscountAmount) AS Discounts
      FROM Receipt r
           INNER JOIN Orders o ON o.OrderID = r.OrderID
           INNER JOIN [User] u ON u.UserID = o.UserID
       GROUP BY u.UserID, u.UserName
     ) d
     on s.userId = d.userId and s.userName = d.userName

我认为发生的事情是您将每个项目的收据记录相乘。使用连接将数据简单地汇集在一起​​时需要非常小心。对于此类聚合,子查询是您的朋友。

如果您需要获取所有行(即,两侧可能存在不匹配),请将联接切换为full outer join并使用:

select coalesce(s.userId, d.userId) as userId, coalesce(s.userName, d.userName) as userName, . . .

答案 1 :(得分:0)

收据的内部联接可能是排除某些订单(并非所有订单都有收据,右边)和重复计算其他订单(一个订单可能有很多收据?)