从子查询/联接的同一个表更新MySQL表

时间:2018-12-05 12:26:31

标签: mysql sql sql-update

我在此问题上看到了很多问题,但无法解决。 我想基于同一表中的计算值来更新表中的多列(但将从一开始)。
这是每个客户每月的交易列表。

TransID | Cust | Month      | Value | PastValue | FutureValue
      1 |    1 | 2018-01-01 |    45 |
      2 |    1 | 2018-02-01 |     0 |  
      3 |    1 | 2018-03-01 |    35 |
      4 |    1 | 2018-04-01 |    80 |

UPDATE tbl_transaction a
SET PrevMnthValue = 
(SELECT COUNT(TransactionID) FROM tbl_transaction b WHERE b.Cust=a.Cust AND b.Month<a.Month)

但是我们得到了可怕的信息:“无法使用带有同一表的子查询的where来更新表)。

我已尝试嵌套子查询,因为有人吹捧它是一种解决方法:

UPDATE tbl_transactions a 
SET 
    PastValue = 
        (
            SELECT CNT FROM
                (
                    SELECT 
                    COUNT(TransactionID) AS CNT
                    FROM tbl_transactions b
                    WHERE
                        b.CustomerRef=a.CustomerRef AND b.Month<a.Month
                ) x
        ),
    FutureValue = 
        (
            SELECT CNT FROM
                (
                    SELECT 
                    COUNT(TransactionID) AS CNT
                    FROM tbl_transactions b
                    WHERE
                        b.CustomerRef=a.CustomerRef AND b.Month>a.Month
                ) x
        )

但是我在WHERE子句中得到了一个未知的a.CustomerRef。我要去哪里错了?

2 个答案:

答案 0 :(得分:1)

您不能同时更新和读取一张表。 MySQL文档对此进行了说明

  

You cannot update a table and select from the same table in a subquery

首先,您必须选择必要的数据并将其保存到某个地方,例如保存到temporary table

CREATE TEMPORARY TABLE IF NOT EXISTS `temp` AS (
   SELECT 
     COUNT(`TransactionID`) AS CNT,
     `CustomerRef`,
     `Month`
   FROM `tbl_transactions`
   GROUP BY `Custom,erRef`, `Month`
);

之后,您可以使用JOIN语句更新表

UPDATE `tbl_transactions` RIGTH
JOIN `temp` ON `temp`.`CustomerRef` = `tbl_transactions`.`CustomerRef`
AND `temp`.`Month` < `tbl_transactions`.`Month`
SET `tbl_transactions`.`PastValue` = `temp`.`cnt`

已更新:如果要通过不同条件更新几列,则可以组合临时表,UPDATE + RIGHT JOIN和CASE语句。例如:

UPDATE `tbl_transactions`
RIGTH JOIN `temp` ON `temp`.`CustomerRef` = `tbl_transactions`.`CustomerRef` 
SET `tbl_transactions`.`PastValue` = CASE
    WHEN `temp`.`Month` < `tbl_transactions`.`Month` THEN `temp`.`cnt`
    ELSE `tbl_transactions`.`PastValue`
END, 
`tbl_transactions`.`FutureValue` = CASE
    WHEN `temp`.`Month` > `tbl_transactions`.`Month` THEN `temp`.`cnt`
    ELSE `tbl_transactions`.`FutureValue`
END

答案 1 :(得分:0)

您可以在下面尝试

UPDATE tbl_transactions a 
Join
( SELECT CustomerRef,COUNT(TransactionID) AS CNT FROM tbl_transactions b 
group by CustomerRef)x
SET PastValue = CNT 
WHERE x.CustomerRef=a.CustomerRef AND x.Month<a.Month