MySQL — копировать или обновлять строки с изменением в пределах одной таблицы

#mysql

#mysql

Вопрос:

У меня есть таблица базы данных, подобная этой:

 group | detailsID | price
EK    |         1 |  1.40
EK    |         2 |  1.50
EK    |         3 |  1.60
H     |         1 |  2.40
H     |         2 |  2.50
  

Теперь я хочу скопировать данные из группы «EK» в группу «H», поэтому цены для идентификаторов detailsID должны быть скорректированы для идентификаторов DETAILSID 1 и 2, а запись для идентификатора detailsID 3 должна быть вставлена для группы «H».

Как я могу сделать это с помощью одного или двух запросов MySQL?

Спасибо!

Комментарии:

1. Возможно ли, что могут быть H значения без соответствующего EK значения? например, H группа с detailsID = 4 , но нет EK группы с detailsID = 4 ?

2. @Nick Нет, это невозможно

3. Это одноразовое действие, которое вы хотите выполнить?

4. Если это так, то ответ @TimBiegeleisen должен делать то, что вы хотите.

5. @Nick :-0 :-0 Также может быть возможно с использованием SP

Ответ №1:

Мы можем попробовать выполнить INSERT INTO ... SELECT с ON DUPLICATE KEY UPDATE :

 INSERT INTO yourTable (`group`, detailsID, price)
SELECT 'H', detailsID, price
FROM yourTable t
WHERE `group` = 'EK'
ON DUPLICATE KEY UPDATE price = t.price;
  

Но это предполагает, что существует уникальный ключ на (group, detailsID) . Если бы это было невозможно, то этот подход не работал бы.

В качестве альтернативы я мог бы сделать это в два этапа. Сначала удалите записи H группы, затем вставьте обновленные H записи, которые вы ожидаете.

 DELETE
FROM yourTable
WHERE `group` = 'H';

INSERT INTO yourTable (`group`, detailsID, price)
SELECT 'H', detailsID, price
FROM yourTable
WHERE `group` = 'EK';
  

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

Обратите внимание, что вам следует избегать присвоения имен вашим столбцам и таблицам с использованием зарезервированных ключевых слов MySQL, таких как GROUP .

Комментарии:

1. Спасибо за вашу помощь. Я думаю, что первый подход не сработает в моем случае, потому что у меня также есть столбец ID с первичным ключом. Я забыл упомянуть об этом. Я воспользуюсь вашим вторым подходом. Спасибо.

Ответ №2:

Вы также можете попробовать это, следуя коду, реализованному с использованием хранимых процедур. Очень просто, не так сложно понять. Возможно, вам потребуется изменить тип данных и оптимизировать код в соответствии с требованиями.

 DELIMITER $$;

DROP PROCEDURE IF EXISTS update_H $$;

CREATE PROCEDURE update_H()
BEGIN

DECLARE finished INTEGER DEFAULT 0;
DECLARE `group_col` varchar(255) DEFAULT "";
DECLARE `detaildid_col` varchar(255) DEFAULT "";
DECLARE `price_col` varchar(255) DEFAULT "";

DECLARE  H_FOUND INTEGER DEFAULT 0;

DECLARE pull_data CURSOR FOR select `group`, `detaildid`, `price` from test.newtab WHERE `group` = 'EK';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;


OPEN pull_data;
traverse_data: LOOP

FETCH pull_data INTO group_col, detaildid_col, price_col;
IF finished = 1 THEN 
LEAVE  traverse_data;
END IF;

SET H_FOUND = (SELECT count(*) from test.newtab where `group` = 'H' AND `detaildid` = detaildid_col);

IF ( H_FOUND = 1 ) THEN
        UPDATE  test.newtab SET `price` = price_col where `group` = 'H' AND `detaildid` = detaildid_col;
ELSE
    INSERT INTO test.newtab (`group`, `detaildid`, `price`)  VALUES ('H', detaildid_col, price_col); 
END IF;

END LOOP traverse_data;
CLOSE pull_data;

END $$;
DELIMITER ;
  

Вы можете вызвать эту процедуру, выполнив, call update_H();