美好的一天,
我正在尝试为我的库存报告加入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
请参阅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')
我的结果是:
这是正确的数据。
我还在我的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')
结果:
总共会:15-quatitySold。
我只是因为我的查询得到3269而感到困惑,因为真正的openQty应该只有467.
我想这个问题出现在我的查询中,加入了多少事务,然后将它总结起来(我真的不知道)。
你能帮我识别一下,并帮我提出正确的查询。
答案 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