简体   繁体   中英

Update MySQL Table from Subquery/Joined Same Table

I've seen many questions along this issue, but can't get this to work. I want to UPDATE multiple columns in a table (but will start with one) based upon a calculated value from the same table.
It is a list of transactions per customer, per month.

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)

But we get the dreaded 'Can't update a table using a where with a subquery of the same table).

I've tried to nest the subquery as this has been touted as a workaround:

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
        )

But I get an UNKNOWN a.CustomerRef in WHERE clause. Where am I going wrong?

You can't update and read from one table at the same time. MySQL documentation tell about it

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

At first you must select necessary data and save them to somewhere, for example to 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`
);

After it, you can use JOIN statement for update table

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

UPDATED: if you want to update several columns by different condition you can combine temporary table, UPDATE + RIGHT JOIN and CASE statement. For example:

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

You can try below

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM