У меня есть следующая таблица mysql
+---------------------+------+ | time | val | +---------------------+------+ | 2005-02-03 00:00:00 | 2.11 | | 2005-02-04 00:00:00 | 2.11 | | 2005-02-05 00:00:00 | NULL | | 2005-02-06 00:00:00 | NULL | | 2005-02-07 00:00:00 | 3.43 | | 2005-02-08 00:00:00 | NULL | | 2005-02-09 00:00:00 | NULL | | 2005-02-10 00:00:00 | 5.66 | | 2005-02-11 00:00:00 | 5.66 | | 2005-02-12 00:00:00 | NULL | +---------------------+------+
Я хочу создать алгоритм (в PHP), который заполняет значения NULL на основе последнего ненулевого значения. Таким образом, таблица станет следующей
+---------------------+------+ | time | val | +---------------------+------+ | 2005-02-03 00:00:00 | 2.11 | | 2005-02-04 00:00:00 | 2.11 | | 2005-02-05 00:00:00 |>2.11 | | 2005-02-06 00:00:00 |>2.11 | | 2005-02-07 00:00:00 | 3.43 | | 2005-02-08 00:00:00 |>3.43 | | 2005-02-09 00:00:00 |>3.43 | | 2005-02-10 00:00:00 | 5.66 | | 2005-02-11 00:00:00 | 5.66 | | 2005-02-12 00:00:00 |>5.66 | +---------------------+------+
Я ищу подсказки о том, как подойти к этой ситуации. Я использую PHP-Laravel.
Здесь используется SQLFiddle для стандартного SQL.
Как видно из комментариев, вы должны исправлять это при заполнении таблицы. Тем не менее, это можно сделать в PHP или MySQL. Вот один из вариантов:
SET @x:=0; SELECT `time`, IF(val IS NOT NULL, @x:=val, @x) AS val FROM yourtable ORDER BY `time`;
Имейте в виду, что ваш результат изменится в зависимости от порядка и WHERE
и так далее. Используйте SET @x:=0;
для определения значения по умолчанию для случаев, когда первая строка имеет значение NULL
.
Если вам необходимо фиксировать данные на постоянной основе, а не для одного запроса, вы можете обновить таблицу с помощью «правильных» значений:
SET @x:=0; UPDATE yourtable SET val=IF(val IS NOT NULL, @x:=val, @x) ORDER BY `time`;
Если вы хотите использовать только SQL, вы можете использовать этот запрос UPDATE:
UPDATE tab INNER JOIN ( SELECT t1.time, MAX(t2.time) prev_time FROM tab t1 INNER JOIN tab t2 ON t1.time>t2.time WHERE t1.val IS NULL AND t2.val IS NOT NULL GROUP BY t1.time ) p ON tab.time = p.time INNER JOIN tab t2 ON p.prev_time = t2.time SET tab.val = t2.val
Пожалуйста, см. Скрипку здесь .
Подзапрос вернет для каждой строки NULL предыдущую дату с не-NULL значением. Затем я присоединяюсь к таблице с собой, чтобы получить значение и обновить нулевую строку.