Как обновить каждую строку в разные значения в MySQL? - PullRequest
1 голос
/ 06 марта 2020
id INT | food TEXT  | memo TEXT         
   1   | Cucumbers  |   NULL
   2   | Dandelions |   NULL
   3   | Salmons    |   NULL
   3   | Cucumbers  |   NULL
   4   | Tomatoes   |   NULL

Вечер.

У меня есть таблица с именем results, которая разбивает каждое food значение на несколько строк, как указано выше.

Столбец с именем id относится к отдельное животное, а колонка food - это то, что животные едят.

Я бы хотел заполнить столбец memo, используя ключевые слова REPLACE или UPDATE, например:

   3   | Salmons    |   Mostly liked it, only 15% didn't eat.
   3   | Cucumbers  |   Only 10% have eaten, rest of all didn't even try. 

Проблема в том, что MySQL всегда обновляет одну и ту же строку как это:

   3   | Salmons    |   Mostly liked it, only 15% didn't eat.
   3   | Cucumbers  |   Mostly liked it, only 15% didn't eat.

Это мой прогресс:

DROP FUNCTION IF EXISTS fx_length;
DROP FUNCTION IF EXISTS fx_splitter;
DROP FUNCTION IF EXISTS fx_split_row;
DROP PROCEDURE IF EXISTS App_forEach_memo;

DELIMITER //
    CREATE FUNCTION fx_length(str TEXT, del VARCHAR(2), pos INT)
        RETURNS INT
        RETURN LENGTH(SUBSTRING_INDEX(str, del, pos - 1)) + 1 //

    CREATE FUNCTION fx_splitter(str TEXT, del VARCHAR(2), pos INT)
        RETURNS TEXT
        RETURN SUBSTRING(SUBSTRING_INDEX(str, del, pos), fx_length(str, del, pos)) //

    CREATE FUNCTION fx_split_row(str TEXT, del VARCHAR(2), pos INT)
        RETURNS TEXT
            BEGIN
                DECLARE output TEXT;
                SET output = REPLACE(fx_splitter(str, del, pos), del, '');
                IF output = '' THEN SET output = NULL; END IF;
                RETURN output;
            END //

    CREATE PROCEDURE App_forEach(IN target INT, strings TEXT)
        BEGIN
            DECLARE i INT DEFAULT 1;
            REPEAT
                UPDATE results 
                    SET id = target, memo = fx_split_row(strings, '| ', i) 
                    WHERE id = target;
                SET i = i + 1;
                UNTIL i = target
            END REPEAT;
        END //
DELIMITER ;
CALL App_forEach(3, "Mostly liked it, only 15% didn't eat.| Only 10% have eaten, rest of all didn't even try.");

Я думаю, мне нужно изменить эту часть SET id = target . . . для подсчета на те же самые id чисел, но я не не знаю, как это сделать.

Есть ли способы обновить значения memo без создания дополнительной временной таблицы?

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

Спасибо.

1 Ответ

1 голос
/ 06 марта 2020
WITH cte AS ( SELECT food, ROW_NUMBER() OVER () rn
              FROM results 
              WHERE @id = id )
UPDATE results, cte
SET results.memo = TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(@memo, '|', cte.rn), '|', -1))
WHERE results.food = cte.food
  AND results.id = @id
  AND cte.rn <= 1 + LENGTH(@memo) - LENGTH(REPLACE(@memo, '|', ''));

fiddle

При необходимости вы можете поместить этот запрос в процедуру.

Если у вас есть древняя версия MySQL, которая не поддерживает CTE и затем оконные функции эмулируют их в подзапросе с использованием пользовательских переменных.

...