MySQL从具有用户变量的视图中选择 - 意外结果

时间:2009-11-03 08:39:49

标签: mysql user-variables

我有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 =&gt; 3(好)
在第2行:-0.5 =&gt; 2.5(好的)
在第3行:+1 =&gt; 3.2 (???)
在第4行:-0.3 =&gt; 2.2 (???)

在执行语句时,似乎MySQL没有采用ORDER BY子句中指定的行的顺序,并且它会查找id:在 > ID为3的文档('2009-10-21'&lt;'2009-10-28')

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

1 个答案:

答案 0 :(得分: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