0

我有 2 张桌子和一个视图。在product_oper我有一些我收到的产品(何时id_dest为 1)和我出售的产品(何时id_src为 1)。该表product_doc包含操作发生的日期。

CREATE TABLE product_doc (
  id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  doc_date date NOT NULL,
  doc_no char(16) NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB;

INSERT INTO product_doc (id,doc_date,doc_no) VALUES 
 (1,'2009-10-07','1'),
 (2,'2009-10-14','2'),
 (3,'2009-10-28','4'),
 (4,'2009-10-21','3');

CREATE TABLE product_oper (
  id bigint(12) unsigned NOT NULL AUTO_INCREMENT,
  id_document bigint(20) unsigned NOT NULL,
  prod_id bigint(12) unsigned NOT NULL DEFAULT '0',
  prod_quant decimal(16,4) NOT NULL DEFAULT '1.0000',
  prod_value decimal(18,2) NOT NULL DEFAULT '0.00',
  id_dest bigint(20) unsigned NOT NULL,
  id_src bigint(20) unsigned NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB;

INSERT INTO product_oper (id,id_document,prod_id,prod_quant,prod_value,id_dest,id_src) 
  VALUES 
  (10,1,1,'2.0000', '5.00',1,0),
  (11,3,1,'0.5000', '1.20',0,1),
  (12,1,2,'3.0000','26.14',1,0),
  (13,2,2,'0.5000','10.20',0,1),
  (14,3,2,'0.3000', '2.60',0,1),
  (15,4,2,'1.0000', '0.40',1,0);

在视图中,我想查看所有操作和日期。

CREATE VIEW product_oper_view AS
 SELECT product_oper.*, product_doc.doc_date AS doc_date, product_doc.doc_no AS doc_no
 FROM product_oper JOIN product_doc ON product_oper.id_document = product_doc.id
 WHERE 1;

现在我想看看单个产品的操作,以及特定日期的数量和价值。

SET @amount=0.000, @balance=0.00;

SELECT product_oper_view.*,
  IF(id_dest<>0, prod_quant, NULL) AS q_in,
  IF(id_dest<>0, prod_value, NULL) AS v_in,
  IF(id_src<>0, prod_quant, NULL) AS q_out,
  IF(id_src<>0, prod_value, NULL) AS v_out,
  @amount:=@amount + IF(id_dest<>0, 1, -1)*prod_quant AS q_amount,
  @balance:=@balance + IF(id_dest<>0, 1, -1)*prod_value AS v_balance
FROM product_oper_view 
WHERE prod_id=2 AND (id_dest=1 OR id_src=1)
ORDER BY doc_date;

我得到的结果很奇怪:

id, id_ prod_ prod_  id_ id_    doc_date,   q_in,   v_in,                 q_      v_
   doc, quant,value,dest,src,                              q_out, v_out, amount,  balance
12, 1, 3.0000, 26.14, 1,  0, '2009-10-07', 3.0000, 26.14,  NULL ,  NULL,  3.000,  26.14
13, 2, 0.5000, 10.20, 0,  1, '2009-10-14',  NULL ,  NULL, 0.5000, 10.20,  2.500,  15.94
15, 4, 1.0000,  0.40, 1,  0, '2009-10-21', 1.0000,  0.40,  NULL ,  NULL,  3.200,  13.74
14, 3, 0.3000,  2.60, 0,  1, '2009-10-28',  NULL ,  NULL, 0.3000,  2.60,  2.200,  13.34

金额从零开始,
在第 1 行:+3 => 3 (ok)
在第 2 行:-0.5 => 2.5 (ok)
在第 3 行:+1 => 3.2 (???)
在第 4 行:-0.3 => 2.2 (???)

看来MySQLORDER BY在执行语句时并没有按照子句中指定的行顺序,而是在id之后查找: See that document with id 4 is before document with id 3 ('2009-10-21' < ' 2009-10-28')

我做错了什么,还是 MySQL 的错误?

4

1 回答 1

0

如果我没有完全错,那么ORDER- 操作是准备结果集时完成的最后一件事。因此,您的计算是在订购结果之前完成的。规避此问题的正确方法应该是使用子选择:

SET @amount=0.000, @balance=0.00;

SELECT p.*,
    @amount:=@amount + IF(p.id_dest <> 0, 1, -1) * p.prod_quant AS q_amount,
    @balance:=@balance + IF(p.id_dest <> 0, 1, -1) * p.prod_value AS v_balance
FROM (
    SELECT product_oper_view.*,
        IF(product_oper_view.id_dest <> 0, product_oper_view.prod_quant, NULL) AS q_in,
        IF(product_oper_view.id_dest <> 0, product_oper_view.prod_value, NULL) AS v_in,
        IF(product_oper_view.id_src <> 0, product_oper_view.prod_quant, NULL) AS q_out,
        IF(product_oper_view.id_src <> 0, product_oper_view.prod_value, NULL) AS v_out
    FROM product_oper_view 
    WHERE product_oper_view.prod_id = 2 
        AND (product_oper_view.id_dest = 1 OR product_oper_view.id_src = 1)
    ORDER BY product_oper_view.doc_date
) AS p
于 2009-11-03T08:56:50.523 回答