0

次のように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

上記のクエリでは、正しい残高が得られません。助けてください。

追加情報: 以下は、私のテーブル Products テーブルの簡略化された構造です。

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(またはスキーマの変更)を提案できますか?

4

1 に答える 1

2

まず、句に追加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すべてのテーブルのデータ型を同じにすることをお勧めします。それvarcharproductsintあるsales/stock

私はあなたのためにフィドルをしました

于 2012-04-09T19:46:24.877 に答える