使用多个JOINS。 SUM()产生错误的值

时间:2010-02-20 18:12:28

标签: sql sum join

我在SQL查询中获取一些基本发票信息,并在同一查询中计算订单总额和付款总额。以下是我到目前为止的情况:

SELECT
    orders.billerID, 
    orders.invoiceDate, 
    orders.txnID, 
    orders.bName, 
    orders.bStreet1, 
    orders.bStreet2, 
    orders.bCity, 
    orders.bState, 
    orders.bZip, 
    orders.bCountry, 
    orders.sName, 
    orders.sStreet1, 
    orders.sStreet2, 
    orders.sCity, 
    orders.sState, 
    orders.sZip, 
    orders.sCountry, 
    orders.paymentType, 
    orders.invoiceNotes, 
    orders.pFee, 
    orders.shipping, 
    orders.tax, 
    orders.reasonCode, 
    orders.txnType, 
    orders.customerID, 
    customers.firstName AS firstName, 
    customers.lastName AS lastName, 
    customers.businessName AS businessName, 
    orderStatus.statusName AS orderStatus, 
    SUM((orderItems.itemPrice * orderItems.itemQuantity))
      + orders.shipping + orders.tax AS orderTotal, 
    SUM(payments.amount) AS totalPayments                       <-- this sum
FROM
    orders 
    LEFT JOIN customers ON orders.customerID = customers.id 
    LEFT JOIN orderStatus ON orders.orderStatus = orderStatus.id
    LEFT JOIN payments ON payments.orderID = orders.id          <-- this join
    LEFT JOIN orderItems ON orderItems.orderID = orders.id 

除了totalPayments列之外,所有内容都非常出色。数据库中有一个付款,其值为(10.00)。查询提供的值是20.00(正好是两倍)。我的理论是,由于某种原因,查询是两次“汇总”付款金额列。任何人都可以为我阐明这一点吗?

感谢您的帮助!

3 个答案:

答案 0 :(得分:20)

如果您在没有group by的情况下运行查询,您会看到某些付款有多行。那是因为你也加入了订单商品。对于orderitem和payment的每个组合,结果集将包含一行。

一种解决方案是将总和更改为:

,    <earlier columns>    
,    (   select SUM(payments.amount) 
         from payments 
         where payments.orderID = orders.id
     ) AS totalPayments
,    <later columns>

这将确保多次订购的付款不会多次汇总。

答案 1 :(得分:0)

我的猜测是付款是10美元,订单中有两个项目(orderitems表)。如果是这种情况,请尝试在orders / customers / orderstatus字段上使用GROUP BY。

答案 2 :(得分:0)

一种解决方案是对每个 JOIN 进行嵌套查询。它应该比使用相关查询(由 Andomar 建议)快得多,并且适用于符合 ANSI SQL 标准的数据库系统。

未经测试的示例:

SELECT
  orders_with_payments.billerID,
  orders_with_payments.invoiceDate,
  orders_with_payments.totalPayments,
  SUM(orderItems.itemPrice) AS orderTotal,
  ...
FROM (
  SELECT
    orders.billerID,
    orders.invoiceDate,
    SUM(payments.amount) AS totalPayments,
    ...
  FROM orders
  LEFT JOIN payments ON payments.orderID = orders.id
) orders_with_payments
LEFT JOIN orderItems ON orderItems.orderID = orders_with_payments.id