Reputation: 704
I wish to update table1 with any distinct value of table2 matching the same code, no matter which one or the order (value from table2 can't be picked more than once)
+-------------------+ +--------------+
| table1 | | table2 |
+-------------------+ +--------------+
| id | code | value | | code | value |
+----+------+-------+ +------+-------+
| 1 | A | | <-- | A | v1 |
| 2 | A | | | B | v2 |
| 3 | B | | | A | v3 |
+----+------+-------+ | A | v5 |
| A | v6 |
+------+-------+
+-------------------+
| table1 |
+-------------------+
| id | code | value |
+----+------+-------+
| 1 | A | v6 |
| 2 | A | v3 |
| 3 | B | v2 |
+----+------+-------+
How can I write the SQL update statement ? (MySQL 5.7)
Upvotes: 1
Views: 64
Reputation: 704
The statement provided by Madhur Bhaiya does work if
The statement should be
UPDATE
table1 AS t1
JOIN
(SELECT
dt1.id,
IF(@cd1 = dt1.code, @rn1 := @rn1 + 1, 1) AS row_num1,
@cd1 := dt1.code AS code,
FROM (SELECT id, code FROM table1 ORDER BY code, id) AS dt1
CROSS JOIN (SELECT @rn1 := 1, @cd1 := '') AS init1
) AS t2
ON t2.id = t1.id
JOIN
(SELECT
IF(@cd2 = dt2.code, @rn2 := @rn2 + 1, 1) AS row_num2,
@cd2 := dt2.code AS code,
dt2.value
FROM (SELECT DISTINCT code, value FROM table2 ORDER BY code) AS dt2
CROSS JOIN (SELECT @rn2 := 1, @cd2 := '') AS init2
) AS t3
ON t3.row_num2 = t2.row_num1 AND
t3.code = t2.code
SET t1.value = t3.value
Upvotes: 1
Reputation: 28844
This requires Row_Number()
Window function's magic! Unfortunately, your MySQL version is 5.7; so a more verbose solution using User-defined variables follows:
UPDATE
table1 AS t1
JOIN
(SELECT
dt1.id,
IF(@cd1 = dt1.code, @rn1 := @rn1 + 1, 1) AS row_num1,
@cd1 := dt1.code AS code
FROM (SELECT id, code FROM table1 ORDER BY code, id) AS dt1
CROSS JOIN (SELECT @rn1 := 0, @cd1 := '') AS init1
) AS t2
ON t2.id = t1.id
JOIN
(SELECT
IF(@cd2 = dt2.code, @rn2 := @rn2 + 1, 1) AS row_num2,
@cd2 := dt2.code AS code,
dt2.value
FROM (SELECT code, value FROM table2 ORDER BY code) AS dt2
CROSS JOIN (SELECT @rn2 := 0, @cd2 := '') AS init2
) AS t3
ON t3.row_num2 = t2.row_num1 AND
t3.code = t2.code
SET t1.value = t3.value
You can check the explanation of a similar technique in this answer.
Upvotes: 1
Reputation: 1
Using OVER functions should work:
Example queries:
select id,code,value,rank() over (partition by code order by id asc) rank_
from dbo.table1;
select code,value,dense_rank() over (partition by code order by code,value asc) rank_ from dbo.table2;
Update statment:
UPDATE t
SET t1.value = t2.value
FROM (select id,code,value,rank() over (partition by code order by id asc) rank_ from dbo.table1) t1
inner join ( select code,value,dense_rank() over (partition by code order by code,value asc) rank_ from dbo.table2 ) t2
on t1.code = t2.code and t1.rank_ = t2.rank_
Upvotes: 0
Reputation: 31991
use join ,As order does not matter so i think your sample output could be changed
UPDATE table1 a
JOIN table2 b ON a.code= b.code
set a.value = b.value
Upvotes: 0