Инструкция SQL: как я могу выбрать значение только один раз из таблицы, чтобы обновить другую таблицу? - PullRequest
0 голосов
/ 09 ноября 2018

Я хочу обновить table1 любым другим значением table2, соответствующим одному и тому же коду, независимо от того, какой из них или порядок (значение из table2 не может быть выбрано более одного раза)

+-------------------+      +--------------+
|      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   |
+----+------+-------+

Как можноЯ пишу заявление об обновлении SQL?(MySQL 5.7)

Ответы [ 4 ]

0 голосов
/ 10 ноября 2018

Заявление, предоставленное Мадхур Бхайя действительно работает, если

  1. @ rn * инициализируются в 1 вместо 0 (в противном случае row_num * нумеруются 1 дважды)
  2. ВЫБРАТЬ из таблицы2 - ОТЛИЧНО (потому что пары (код, значение) повторяются в таблице2)

Заявление должно быть

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 
0 голосов
/ 09 ноября 2018

Это требует Row_Number() Волшебство оконной функции! К сожалению, ваша версия MySQL 5.7; поэтому следует более подробное решение с использованием пользовательских переменных :

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 

Вы можете проверить объяснение подобной техники в этом ответе .

0 голосов
/ 09 ноября 2018

Использование функций OVER должно работать:

Примеры запросов:

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 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_
0 голосов
/ 09 ноября 2018

используйте соединение, так как порядок не имеет значения, поэтому я думаю, что ваш пример вывода может быть изменен

    UPDATE table1 a 
    JOIN table2 b ON a.code= b.code 
    set a.value = b.value 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...