【问题标题】:Update the total based on the previous row of balance根据上一行余额更新总计
【发布时间】:2016-06-09 09:57:55
【问题描述】:

这是数据库数据。

Name   id  Col1  Col2  Col3 Col4 Total  Balance
Row1   1    6     1     A     Z     -      - 
Row2   2    2     3     B     Z     -      - 
Row3   3    9     5     B     Y     -      - 
Row4   4    16    8     C     Y     -      -

我想根据条件将“总计”和“余额”列从第 2 行更新到第 4 行。这是对总列求和的逻辑:

如果 Col3 = A 和 Col4 Z
,则更新 Total = Col1+Col2 或
总计 = Col1-Col2 如果 Col3 = B 和 Col4 Z

总计 = Col1*Col2 如果 Col3 = C 和 Col4 Z

并且还更新余额,

余额 = 上一行余额 + 当前行总计

【问题讨论】:

  • 在 select 子句中使用 case 进行条件操作。另外,我认为它需要存储过程来逐行更新表。
  • 您介意展示一个示例吗?
  • 感谢您的关注
  • 发布了一个数据已验证的答案。请检查是否如您所愿。

标签: mysql sql


【解决方案1】:

这是一个借助一个用户变量的解决方案。

结果已通过附加完整演示验证。

SQL:

-- data preparation for demo
create table tbl(Name char(100), id int, Col1 int, Col2 int, Col3 char(20), Col4 char(20), Total int, Balance int);
insert into tbl values
('Row1',1,6,1,'A','Z',0,0),
('Row2',2,2,3,'B','Z',0,0),
('Row3',3,9,5,'B','Y',0,0),
('Row4',4,12,8,'C','Y',0,0);
SELECT * FROM tbl;

-- Query needed
SET @bal = 0;
UPDATE tbl
SET
    Total = CASE    WHEN Col3 = 'A' and Col4 <> 'Z'
                        THEN Col1+Col2
                    WHEN Col3 = 'B' and Col4 <> 'Z'
                        THEN Col1-Col2
                    WHEN Col3 = 'C' and Col4 <> 'Z'
                        THEN Col1*Col2
                    ELSE 0 END,
    Balance = (@bal:=@bal + Total);
SELECT * FROM tbl;

输出(如预期):

mysql> SELECT * FROM tbl;
+------+------+------+------+------+------+-------+---------+
| Name | id   | Col1 | Col2 | Col3 | Col4 | Total | Balance |
+------+------+------+------+------+------+-------+---------+
| Row1 |    1 |    6 |    1 | A    | Z    |     0 |       0 |
| Row2 |    2 |    2 |    3 | B    | Z    |     0 |       0 |
| Row3 |    3 |    9 |    5 | B    | Y    |     0 |       0 |
| Row4 |    4 |   12 |    8 | C    | Y    |     0 |       0 |
+------+------+------+------+------+------+-------+---------+
4 rows in set (0.00 sec)

mysql> -- Query needed
mysql> SET @bal = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE tbl
    -> SET
    ->     Total = CASE    WHEN Col3 = 'A' and Col4 <> 'Z'
    ->                         THEN Col1+Col2
    ->                     WHEN Col3 = 'B' and Col4 <> 'Z'
    ->                         THEN Col1-Col2
    ->                     WHEN Col3 = 'C' and Col4 <> 'Z'
    ->                         THEN Col1*Col2
    ->                     ELSE 0 END,
    ->     Balance = (@bal:=@bal + Total);
Query OK, 2 rows affected (0.00 sec)
Rows matched: 4  Changed: 2  Warnings: 0

mysql>
mysql> SELECT * FROM tbl;
+------+------+------+------+------+------+-------+---------+
| Name | id   | Col1 | Col2 | Col3 | Col4 | Total | Balance |
+------+------+------+------+------+------+-------+---------+
| Row1 |    1 |    6 |    1 | A    | Z    |     0 |       0 |
| Row2 |    2 |    2 |    3 | B    | Z    |     0 |       0 |
| Row3 |    3 |    9 |    5 | B    | Y    |     4 |       4 |
| Row4 |    4 |   12 |    8 | C    | Y    |    96 |     100 |
+------+------+------+------+------+------+-------+---------+
4 rows in set (0.00 sec)

【讨论】:

  • 谢谢迪伦。您的查询最短,结果符合我的预期!非常感谢!
  • Dylan Su,你很优秀。我想和你交朋友。
【解决方案2】:
UPDATE tableName t1 SET 
Total =  
CASE
  WHEN t1.Col3 = "A" and t1.Col4 <> "Z" THEN t1.Col1 + t1.Col2
  WHEN t1.Col3 = "B" and t1.Col4 <> "Z" THEN t1.Col1 - t1.Col2
  WHEN t1.Col3 = "C" and t1.Col4 <> "Z" THEN t1.Col1 * t1.Col2
END
Balance = 
CASE
  WHEN t1.Col3 = "A" and t1.Col4 <> "Z" THEN 
  (SELECT t2.Balance FROM tableName t2 
    WHERE t2.id = (select max(t3.id) from tableName t3 where t3.id < t1.id))
    + (t1.Col1 + t1.Col2)
  WHEN t1.Col3 = "B" and t1.Col4 <> "Z" THEN 
  (SELECT t2.Balance FROM tableName t2 
    WHERE t2.id = (select max(t3.id) from tableName t3 where t3.id < t1.id))
    + (t1.Col1 - t1.Col2)
  WHEN t1.Col3 = "C" and t1.Col4 <> "Z" THEN 
  (SELECT t2.Balance FROM tableName t2 
    WHERE t2.id = (select max(t3.id) from tableName t3 where t3.id < t1.id))
    + (t1.Col1 * t1.Col2)
END
WHERE t1.id > 1;

【讨论】:

  • 是的,比较id比较容易,但是id是随机的,不按顺序排列。
  • 所以下一行 id 可能不是 +1,但可能是 +10 或 +100
  • @LimNeo ,那你说的previous row是什么意思
  • 就像Row2的上一行是Row 1
  • 我认为我们需要使用排名来比较结果
【解决方案3】:
SET @prev_id = 1;
UPDATE tableName SET 
Total =  
CASE
  WHEN Col3 = A and Col4 <> Z THEN Col1 + Col2
  WHEN Col3 = B and Col4 <> Z THEN Col1 - Col2
  WHEN Col3 = C and Col4 <> Z THEN Col1 * Col2
END,
Balance = 
CASE
  WHEN Col3 = A and Col4 <> Z THEN 
  (SELECT Balance FROM tableName WHERE id = @prev_id) + (Col1 + Col2)
  WHEN Col3 = B and Col4 <> Z THEN 
  (SELECT Balance FROM tableName WHERE id = @prev_id) + (Col1 - Col2)
  WHEN Col3 = C and Col4 <> Z THEN 
  (SELECT Balance FROM tableName WHERE id = @prev_id) + (Col1 * Col2)
END,
@prev_id := id

WHERE t1.id > 1;

【讨论】:

    【解决方案4】:

    试试这个

     SET @old_balance = 0;
        UPDATE tableName SET 
        Total =  
        CASE
          WHEN Col3 = 'A' and Col4 <> 'Z' THEN Col1 + Col2
          WHEN Col3 = 'B' and Col4 <> 'Z' THEN Col1 - Col2
          WHEN Col3 = 'C' and Col4 <> 'Z' THEN Col1 * Col2
        END,
        Balance = 
        CASE
          WHEN Col3 = 'A' and Col4 <> 'Z' THEN 
          @old_balance + (Col1 + Col2)
          WHEN Col3 = 'B' and Col4 <> 'Z' THEN 
          @old_balance + (Col1 - Col2)
          WHEN Col3 = 'C' and Col4 <> 'Z' THEN 
          @old_balance + (Col1 * Col2)
        END,
        @old_balance := 
        CASE
          WHEN Col3 = 'A' and Col4 <> 'Z' THEN 
          @old_balance + (Col1 + Col2)
          WHEN Col3 = 'B' and Col4 <> 'Z' THEN 
          @old_balance + (Col1 - Col2)
          WHEN Col3 = 'C' and Col4 <> 'Z' THEN 
          @old_balance + (Col1 * Col2)
        END
        WHERE t1.id > 1;
    

    【讨论】:

      猜你喜欢
      • 2022-01-09
      • 1970-01-01
      • 2012-07-03
      • 2013-02-18
      • 2016-07-18
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      相关资源
      最近更新 更多