使用连接和选择的mysql查询结果有问题

时间:2015-09-27 22:42:53

标签: mysql sql join

美好的一天,

我正在尝试为我的库存报告加入3个表格,但我得到了奇怪的结果。

我的查询

SELECT i_inventory.xid,
       count(x_transaction_details.xitem) AS occurrence,
       i_inventory.xitem AS itemName,
       SUM(i_items_group.or_qty) AS `openingQty`,
       avg(x_transaction_details.cost) AS avg_cost,
       SUM(x_transaction_details.qty) AS totalNumberSold,
       SUM(i_items_group.or_qty) - SUM(x_transaction_details.qty) AS totalRemQty
FROM x_transaction_details
LEFT JOIN i_inventory ON x_transaction_details.xitem = i_inventory.xid
LEFT JOIN i_items_group ON i_inventory.xid = i_items_group.xitem
WHERE (x_transaction_details.date_at BETWEEN '2015-01-18 03:14:54' AND '2015-10-18 03:14:54')
  AND i_inventory.xid = 3840
GROUP BY x_transaction_details.xitem
ORDER BY occurrence DESC

此查询为我提供了以下结果: enter image description here

请参阅openingQty列,然后尝试进行简单查询以验证结果

这是我的查询,检查openQty只加入2个表i_items_group表(存储批次)和i_inventory表(项目信息存储)。

SELECT i_inventory.xid,
       i_inventory.xitem,
       SUM(i_items_group.or_qty) AS openingQty,
       i_items_group.cost
FROM i_inventory
INNER JOIN i_items_group ON i_inventory.xid = i_items_group.xitem
WHERE i_inventory.xid = 3840
  AND (i_items_group.date_at BETWEEN '2015-01-18 03:14:54' AND '2015-10-18 03:14:54')

我的结果是:

enter image description here

这是正确的数据。

我还在我的x_transaction_details表上查询了是否正确。

继承人我的疑问:

select xitem, qty as qtySold from x_transaction_details where xitem = 3840 
AND (date_at BETWEEN '2015-01-18 03:14:54' AND '2015-10-18 03:14:54')

结果:

enter image description here

总共会:15-quatitySold。

我只是因为我的查询得到3269而感到困惑,因为真正的openQty应该只有467.

我想这个问题出现在我的查询中,加入了多少事务,然后将它总结起来(我真的不知道)。

你能帮我识别一下,并帮我提出正确的查询。

1 个答案:

答案 0 :(得分:1)

这是单个查询中多个SUM语句的常见问题。请记住SQL如何进行聚合:首先它生成一组未聚合的数据,然后聚合它。在没有GROUP BY或聚合函数的情况下尝试您的查询,您会惊讶于您的结果。我的帖子中没有足够的正确细节来确定故障的位置,但我可以猜到。

看起来您有一个与某种产品相对应的xitem,然后您已将其加入到交易和项目组中。假设特定xitem与3个事务和5个项目组匹配。您将从该加入中获得15条记录。当你总结它时,任何基于事务表中字段的SUM计算都将比你预期的高5倍,并且来自项目组表的任何SUM计算将比你预期的高3倍。这里的关键症状是聚合结果是正确值的倍数,但不同行的看似不同的倍数。

有多种方法可以解决此类错误。一些开发人员喜欢计算子查询中的一个聚合聚合,然后通过子查询中已经正确的结果在主查询和组中执行另一个聚合。其他人喜欢编写内联查询以在表达式中进行聚合:

SELECT xitem, (SELECT SUM(i_items_group.or_qty) FROM i_items_group WHERE i_inventory.xid = i_items_group.xitem) AS `openingQty`
, -- select more fields

找出最适合您的方法。但是如果你想亲自看看证据,那么在聚合消失的情况下运行这个查询,你就会明白为什么这些SUM正在做他们正在做的事情:

SELECT i_inventory.xid,
       x_transaction_details.xitem AS occurrence,
       i_inventory.xitem AS itemName,
       i_items_group.or_qty,
       x_transaction_details.cost,
       x_transaction_details.qty,
       i_items_group.or_qty - x_transaction_details.qty AS RemainingQty
FROM x_transaction_details
LEFT JOIN i_inventory ON x_transaction_details.xitem = i_inventory.xid
LEFT JOIN i_items_group ON i_inventory.xid = i_items_group.xitem
WHERE (x_transaction_details.date_at BETWEEN '2015-01-18 03:14:54' AND '2015-10-18 03:14:54')
  AND i_inventory.xid = 3840

ORDER BY occurrence DESC