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

返回虚假(?)值的MySQL SUM(),mysql,Mysql,尽管花了一个小时在这上面,我还是找不到解决办法。我有一个复杂的ish查询,返回的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

尽管花了一个小时在这上面,我还是找不到解决办法。我有一个复杂的ish查询,返回的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 
为“订购的项目总数”提供了极不正确的数据

+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| 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)
然而,当我从查询中剥离所有复杂度并运行raw 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      |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+

如果您在查询中遗漏了
分组依据
,则错误结果的原因应该很清楚。对于您加入的每个表,返回的行数将乘以加入所找到的行数

由于
materials\u batch
表包含每个订单的多个条目,因此对于订单号15571,结果
total\u items\u 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 

我的SQL有一个扩展的group by,它可以返回意外的结果。禁用扩展分组依据,或定义分组依据中的所有非聚合字段。“服务器可以从每个组中自由选择任何值,因此,除非它们相同,否则选择的值是不确定的。”其次,您的加入可能会导致额外的记录出现在采购订单项目上。供应商或材料批次是否有超过1条记录?如果是这样,那么这也会引起问题。你应该给sqlfiddle.com链接,这样人们可以帮助你更多。@VishalZanzrukia甚至不知道sqlfiddle的存在。。。下次注意!谢谢:)这真的很有道理。我想下一个问题是。。。有什么简单的办法吗?