MySQL SUM()返回虚假(?)值

时间:2014-06-24 13:00:08

标签: mysql

尽管花了一个小时的时间,但解决办法仍然是我。我有一个复杂的查询,它返回SUM()的错误数据。然而,当我将其剥离为最近的形式时,它会输出正确的数据。但为什么并修复,我无法弄明白。

问题

SELECT po.*, SUM( poo.material_qty ) AS total_items_ordered, suppliers.supplier_name
FROM  `purchase_orders` po
LEFT JOIN purchase_orders_items poo ON poo.poid = po.poid
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT 
IN (
'Fulfilled',  'Cancelled'
)
AND batch_status NOT 
IN (
'Arrived',  'Cancelled',  'Refused',  'Missing',  'Damaged',  'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC 

为' total_items_ordered'提供了非常不正确的数据。

+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| poid  | date_raised         | date_expected       | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT     | total    | userid | DN | manual | po_status | total_items_ordered | supplier_name         |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 |           1 |      0 |           0 |        |  14850.10 | 2970.02 | 17820.12 |      1 |    | N      | Raised    |                 545 | John Parker & Son Ltd |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 |           1 |      0 |           0 |        |    997.80 |  199.56 |  1197.36 |      1 |    | N      | Raised    |                  80 | John Parker & Son Ltd |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
2 rows in set (0.00 sec)

然而,当我从查询中删除所有复杂性并运行原始SUM()时,值是正确的:

mysql> SELECT poid, SUM(material_qty) AS total_items_ordered FROM  `purchase_orders_items`  GROUP BY poid;
+-------+---------------------+
| poid  | total_items_ordered |
+-------+---------------------+
| 15571 |                 109 |
| 15572 |                  20 |
+-------+---------------------+
2 rows in set (0.00 sec)

任何人都可以了解我在哪里出错吗?我已经在下面列出了所有测试表内容,以防您发现我错过的内容。谢谢!

数据示例

mysql> SELECT * FROM purchase_orders;
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| poid  | date_raised         | date_expected       | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT     | total    | userid | DN | manual | po_status |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 |           1 |      0 |           0 |        |  14850.10 | 2970.02 | 17820.12 |      1 |    | N      | Raised    |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 |           1 |      0 |           0 |        |    997.80 |  199.56 |  1197.36 |      1 |    | N      | Raised    |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
2 rows in set (0.00 sec)


mysql> SELECT * FROM purchase_orders_items;
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
| poi_id | poid  | material_id | material_qty | material_price | material_sku | material_name                                    |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
|      1 | 15571 |           2 |            3 |         100.00 | PKS275282    | 406x140 White Universal Beam (S355)              |
|      2 | 15571 |           5 |           10 |          17.40 | 118-64-44    | Test Item (S275)                                 |
|      3 | 15571 |           8 |            1 |        9984.50 | 113-64-21    | A really really really big universal beam (S355) |
|      4 | 15571 |           9 |           77 |          10.00 | 12345        | A thing                                          |
|      5 | 15571 |          10 |           18 |         201.20 | 12-34-56     | 102x230 Narrow Beam (S355)                       |
|      6 | 15572 |           2 |            6 |         100.00 | PKS275282    | 406x140 White Universal Beam (S355)              |
|      7 | 15572 |           5 |            9 |          17.40 | 118-64-44    | Test Item (S275)                                 |
|      8 | 15572 |           9 |            4 |          10.00 | 12345        | A thing                                          |
|      9 | 15572 |          10 |            1 |         201.20 | 12-34-56     | 102x230 Narrow Beam (S355)                       |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
9 rows in set (0.00 sec)


mysql> SELECT * FROM suppliers;
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
| supplier_id | supplier_name         | supplier_telephone | supplier_fax | supplier_added_date | supplier_added_by | supplier_last_updated | supplier_last_updated_by | supplier_assessed   | supplier_approved_by |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
|           1 | John Parker & Son Ltd | 01227 783333       | 0800 521932  | 2014-05-04 15:57:43 |                 1 | 2014-06-05 16:38:23   |                        1 | 2014-05-04 15:57:43 |                    2 |
|           2 | Superior Glass Ltd.   | 01825 764766       | 01825 767699 | 2014-05-04 17:48:38 |                 1 | 2014-06-04 20:14:16   |                        1 | 2014-05-04 17:48:38 |                    3 |
|           3 | DTS Origins Ltd.      | 01283 3283029      | 01928 303494 | 2014-05-04 17:51:57 |                 1 | 2014-05-04 17:53:08   |                        1 | 2014-05-04 17:51:57 |                    2 |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
3 rows in set (0.00 sec)


mysql> SELECT * FROM materials_batch;
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
| material_batch_id | poiid | rcvd_date           | purchase_order_no | delivery_note_no | qty | rcvd_by | dn_scanned | material_id | supplier_id | batch_status |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
|                 1 |     1 | 0000-00-00 00:00:00 |             15571 |                  |   3 |       0 | No         |           2 |           1 | Ordered      |
|                 2 |     2 | 0000-00-00 00:00:00 |             15571 |                  |  10 |       0 | No         |           5 |           1 | Ordered      |
|                 3 |     3 | 0000-00-00 00:00:00 |             15571 |                  |   1 |       0 | No         |           8 |           1 | Ordered      |
|                 4 |     4 | 0000-00-00 00:00:00 |             15571 |                  |  77 |       0 | No         |           9 |           1 | Ordered      |
|                 5 |     5 | 0000-00-00 00:00:00 |             15571 |                  |  18 |       0 | No         |          10 |           1 | Ordered      |
|                 6 |     6 | 0000-00-00 00:00:00 |             15572 |                  |   6 |       0 | No         |           2 |           1 | Ordered      |
|                 7 |     7 | 0000-00-00 00:00:00 |             15572 |                  |   9 |       0 | No         |           5 |           1 | Ordered      |
|                 8 |     8 | 0000-00-00 00:00:00 |             15572 |                  |   4 |       0 | No         |           9 |           1 | Ordered      |
|                 9 |     9 | 0000-00-00 00:00:00 |             15572 |                  |   1 |       0 | No         |          10 |           1 | Ordered      |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+

1 个答案:

答案 0 :(得分:2)

当您从查询中遗漏GROUP BY时,应该清楚显示错误结果的原因。对于每个表JOIN,返回的行数乘以JOIN找到的行数。

由于materials_batch表每个订单包含多个条目,因此对于订单号15571,结果total_items_ordered乘以5,对于订单号15572,将其乘以4。

尝试以下方法:

SELECT 
    po.*,
    (
        SELECT SUM(poo.material_qty)
        FROM purchase_orders_items poo
        WHERE poo.poid = po.poid
    ) AS total_items_ordered,
    suppliers.supplier_name
FROM  `purchase_orders` po
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT 
IN (
'Fulfilled',  'Cancelled'
)
AND batch_status NOT 
IN (
'Arrived',  'Cancelled',  'Refused',  'Missing',  'Damaged',  'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC