触发器不能正确计算MySQL的总和

时间:2014-05-20 08:39:23

标签: mysql sql database triggers

我有一个触发器,使用前一行和当前行计算总和,并输出当前行的余额字段中的总和,问题是它似乎无法计算插入表中的第一行的总和我的触发器是:

delimiter $$
CREATE TRIGGER `ledger_calc` AFTER INSERT ON `sp_records`
FOR EACH ROW BEGIN
SET @PrevBal := (SELECT balance FROM ledger WHERE cmp_name = NEW.cmp_name AND inv_for = NEW.inv_for ORDER BY id DESC
LIMIT 1); 
SET @CmpName := NEW.cmp_name;
SET @InvFor := NEW.inv_for;

IF (NEW.type = 'sales') THEN
SET @Type := 'sales';

INSERT INTO ledger (id,inv_for,cmp_name,date,debit,balance)
SELECT
      TransactDet.id,
     TransactDet.inv_for,
    TransactDet.cmp_name,
      TransactDet.date,
      TransactDet.tot_amnt,
      @PrevBal :=  @PrevBal + TransactDet.tot_amnt as balance
   from 
      ( select
              Transact.id,
              Transact.date,
              Transact.tot_amnt,
              Transact.cmp_name,
              Transact.inv_for

           from
              sp_records Transact
           where Transact.type = @Type
            AND Transact.inv_for = @InvFor
            AND Transact.cmp_name = @CmpName
           order by
            Transact.id DESC
            limit 1 ) as TransactDet;
ELSE
SET @Type := 'purchase';
INSERT INTO ledger (id,inv_for,cmp_name,date,credit,balance)
SELECT
      TransactDet.id,
     TransactDet.inv_for,
    TransactDet.cmp_name,
      TransactDet.date,
      TransactDet.tot_amnt,
      @PrevBal := @PrevBal - TransactDet.tot_amnt as balance
   from 
      ( select
              Transact.id,
              Transact.date,
              Transact.tot_amnt,
                Transact.cmp_name,
              Transact.inv_for
           from
              sp_records Transact
           where Transact.type = @Type
            AND Transact.inv_for = @InvFor
            AND Transact.cmp_name = @CmpName
           order by
            Transact.id DESC
            limit 1) as TransactDet;
END IF;

END;

此查询返回了我想要的内容..但它似乎无法转换为触发器...

SELECT
      PreAgg.id,
      PreAgg.tot_amnt,
      @PrevBal := @PrevBal + PreAgg.tot_amnt as balance
   from 
      ( select
              YT.id,
              YT.tot_amnt
           from
              sp_records YT
           order by
              YT.id ) as PreAgg,
      ( select @PrevBal := 0.00 ) as SqlVars

1 个答案:

答案 0 :(得分:1)

请试试这个:

delimiter $$

CREATE TRIGGER `ledger_calc` BEFORE INSERT ON `sp_records`
FOR EACH ROW
BEGIN
    SET @PrevBal : = (
            SELECT balance
            FROM ledger
            WHERE cmp_name = NEW.cmp_name
                AND inv_for = NEW.inv_for
            ORDER BY id DESC LIMIT 1
            );

    INSERT INTO ledger (id, inv_for, cmp_name, DATE, debit, balance)
    SELECT Transact.id, Transact.inv_for, Transact.cmp_name, Transact.DATE, Transact.tot_amnt, @PrevBal + Transact.tot_amnt AS balance
    FROM sp_records Transact
    WHERE Transact.type = NEW.type
        AND Transact.inv_for = NEW.inv_for
        AND Transact.cmp_name = NEW.cmp_name
    ORDER BY Transact.id DESC limit 1;
END $$

我不知道你的桌面结构是什么样的,但你可能会忘记触发器而只是做

INSERT INTO ledger (id, inv_for, cmp_name, DATE, debit, balance)
SELECT t.id, t.inv_for, t.cmp_name, t.DATE, t.tot_amnt, l.balance + t.tot_amnt AS balance
FROM sp_records t
INNER JOIN ledger l ON t.inv_for = l.inv_for AND t.cmp_name = l.cmp_name
WHERE t.type = 'a_value'
    AND t.inv_for = 'another_value'
    AND t.cmp_name = 'yet_another_value'
ORDER BY t.id DESC limit 1;

或作为触发器

DELIMITER $$
CREATE TRIGGER `ledger_calc` AFTER INSERT ON `sp_records`
FOR EACH ROW
BEGIN
    INSERT INTO ledger (id, inv_for, cmp_name, DATE, debit, balance)
    SELECT t.id, t.inv_for, t.cmp_name, t.DATE, t.tot_amnt, l.balance + t.tot_amnt AS balance
    FROM sp_records t
    INNER JOIN ledger l ON t.inv_for = l.inv_for AND t.cmp_name = l.cmp_name
    WHERE t.type = NEW.type
        AND t.inv_for = NEW.inv_for
        AND t.cmp_name = NEW.cmp_name
    ORDER BY t.id DESC limit 1;
END $$

如果这一切都没有帮助,那么样本数据和所需的结果会有所帮助,最好是http://sqlfiddle.com