【问题标题】:Getting stock balance获取库存余额
【发布时间】:2012-04-09 19:41:34
【问题描述】:

我有3张表如下:

products:[product_id,product_name]
stock:[product_id,date,qty_received]
sales:[product_id,date,qty_sold]

我试图通过减去 qty_received - qty_sold 来显示所有产品的余额。 我的查询是:

SELECT DISTINCT p.product_id, p.product_name,
IFNULL(sum(qty_received),0)-IFNULL(sum(qty_sold),0) as balance FROM products p
LEFT JOIN stock st ON (p.product_id=st.product_id)
LEFT JOIN sales sa ON (p.product_id=sa.product_id)
GROUP BY p.product_id

通过上述查询,我​​没有得到正确的余额。 你能帮忙吗?

附加信息: 以下是我的表格的简化结构 产品表:

CREATE TABLE IF NOT EXISTS `products` (
  `product_id` varchar(15) NOT NULL,
  `product_name` varchar(20) NOT NULL,
  UNIQUE KEY `product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- 转储表products的数据

INSERT INTO `products` (`product_id`, `product_name`) VALUES
  ('111', 'Product One'),
  ('222', 'Product Two'),
  ('333', 'Product Three'),
  ('444', 'Product Four');

库存表:

CREATE TABLE IF NOT EXISTS `stock` (
  `stock_id` int(11) NOT NULL AUTO_INCREMENT,
  `product_id` int(11) NOT NULL,
  `qty_received` int(11) NOT NULL,
  PRIMARY KEY (`stock_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=112 ;

-- 转储表stock的数据

INSERT INTO `stock` (`stock_id`, `product_id`, `qty_received`) VALUES
  (1, 111, 5),
  (2, 222, 10),
  (3, 333, 4),
  (4, 444, 6),
  (5, 111, 2),
  (6, 222, 7),
  (7, 111, 3),
  (8, 111, 3);

销售表

CREATE TABLE IF NOT EXISTS `sales` (
  `sales_id` int(11) NOT NULL AUTO_INCREMENT,
  `product_id` int(11) NOT NULL,
  `qty_sold` int(11) NOT NULL,
  PRIMARY KEY (`sales_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

-- 转储表sales的数据

INSERT INTO `sales` (`sales_id`, `product_id`, `qty_sold`) VALUES
  (1, 111, -1),
  (2, 222, -3),
  (3, 333, -2),
  (4, 111, -3),
  (5, 222, -1),
  (6, 222, -4);

我得到的结果是:

+------------+--------------+---------+
| product_id | product_name | balance |
+------------+--------------+---------+
| 111        | Product One  | 10      |
| 222        | Product Two  | 35      |
| 333        | Product Three| 2       |
| 444        | Product Four | 6       |
+------------+--------------+---------+

我期望的正确平衡是

+------------+--------------+---------+
| product_id | product_name | balance |
+------------+--------------+---------+
| 111        | Product One  | 9       |
| 222        | Product Two  | 9       |
| 333        | Product Three| 2       |
| 444        | Product Four | 6       |
+------------+--------------+---------+

终于得到了这个解决方案的工作 sql,但不确定这是否是最好的方法。我非常关心性能,因为这些表有大量记录。

SELECT p.product_id,p.product_name,
IFNULL(sum(st.qty_received),0)+IFNULL(sold,0) as balance FROM products p
  LEFT JOIN stock st ON (p.product_id=st.product_id)
  LEFT JOIN (SELECT sa.product_id,sum(sa.qty_sold) as sold FROM sales sa 
     GROUP BY sa.product_id) as t1 ON (t1.product_id=p.product_id)
GROUP BY product_id

任何人都可以建议更好的 sql(或架构更改)以获得更好的速度/性能来获得库存平衡?

【问题讨论】:

  • sales.qty_sold 是否有可能被存储为负数?
  • 是的,sales.qty_sold 存储为负数,希望它可以让事情变得更容易。
  • 那你就有答案了。您需要 添加 sum(qty_sold) 而不是 减去 它以获得正确的结果。 ...IFNULL(sum(qty_received),0)+IFNULL(sum(qty_sold),0) as balance...
  • @asiph 您当前查询的输入、正确输出和错误输出示例将帮助人们回答。简单地告诉我们“它仍然不起作用”让我们在黑暗中拍摄,可以这么说。

标签: mysql join sum


【解决方案1】:

首先,将p.product_name 添加到GROUP BY 子句。

其次,删除DISTINCT - GROUP BY 没有必要。

更新

我尝试了几个查询,发现这个看起来最简单:

SELECT 
  p.product_id, 
  p.product_name,
  COALESCE(SUM(qty), 0) as balance 
FROM products p 
LEFT JOIN (
    SELECT product_id, qty_received AS qty FROM stock st UNION ALL 
    SELECT product_id, qty_sold FROM sales st
) AS T 
  ON p.product_id = T.product_id
GROUP BY 
  p.product_id, 
  p.product_name

另外,我认为在所有表中将product_id 的数据类型设为相同是个好主意。 products 中的 varcharsales/stock 中的 int

我为你做了一个Fiddle

【讨论】:

  • 它还没有工作。注意负号,如果 qty_sold 存储为负数,则它应该是正数。我还尝试在两个字段中同时显示 qty_received 和 qty_sold,但两个值都是正确余额的倍数。
  • 是的安德烈,我改变了,结果没有改变
  • 您能提供一些示例数据吗?您在产品表上有唯一键吗?
  • product_id 是产品中的唯一键。 stock 表和 sales 表有额外的自动增量键作为唯一键。
猜你喜欢
  • 2017-03-25
  • 1970-01-01
  • 2018-05-04
  • 2013-05-24
  • 2015-11-01
  • 2018-01-20
  • 2011-12-09
  • 2020-12-02
  • 1970-01-01
相关资源
最近更新 更多