Sobes.tech
Назад к вопросам
Junior
13

-- Исходная таблица stretch -- Необходимо в разрезе id заполнить NULL'ы предыдущим значением (не NULL) - выполнить протяжку вниз id | ttime | val ---|-------|----- 1 | 07:30 | NULL 1 | 09:21 | 10 1 | 13:53 | NULL 1 | 16:12 | NULL 2 | 09:42 | 133 2 | 15:20 | NULL 2 | 21:33 | NULL 3 | 08:01 | NULL 3 | 11:41 | 8 3 | 14:23 | NULL 3 | 16:17 | NULL 3 | 19:54 | 2 4 | 13:10 | 312 4 | 14:42 | NULL 4 | 16:31 | 7 4 | 17:44 | NULL id | ttime | val ---|-------|----- 1 | 07:30 | NULL 1 | 09:21 | 10 1 | 13:53 | 10 1 | 16:12 | 10 2 | 09:42 | 133 2 | 15:20 | 133 2 | 21:33 | 133 3 | 08:01 | NULL 3 | 11:41 | 8 3 | 14:23 | 8 3 | 16:17 | 8 3 | 19:54 | 2 4 | 13:10 | 312 4 | 14:42 | 312 4 | 16:31 | 7 4 | 17:44 | 7 -- Слева исходная таблица, а справа, то что нужно получить SELECT id, ttime, COALESCE(val, LAST_VALUE(val) OVER(PARTITION BY id ORDER BY ttime)) as val FROM stretch

Компании, где спрашивали
Яндекс

Ответ от нейросети

sobes.tech AI

Для заполнения NULL значений предыдущим не NULL значением в разрезе id и по времени ttime (протяжка вниз) в SQL можно использовать оконные функции с игнорированием NULL. В PostgreSQL, например, можно применить функцию LAST_VALUE с опцией IGNORE NULLS (если поддерживается), либо использовать MAX с оконным фреймом, или функцию LAG в цикле.

Пример решения с использованием MAX и оконной функции:

SELECT
  id,
  ttime,
  -- берем максимум val по всем предыдущим и текущим строкам в рамках id и упорядоченных по времени
  MAX(val) OVER (PARTITION BY id ORDER BY ttime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS val
FROM stretch
ORDER BY id, ttime;

Это работает, потому что MAX игнорирует NULL и всегда берет максимальное значение из предыдущих строк, что соответствует последнему известному значению.

В вашем примере исходного запроса COALESCE(val, LAST_VALUE(val) OVER(...)) не сработает корректно без IGNORE NULLS, так как LAST_VALUE вернет NULL, если текущий val NULL.

Если СУБД поддерживает IGNORE NULLS, можно написать:

SELECT
  id,
  ttime,
  LAST_VALUE(val) IGNORE NULLS OVER (PARTITION BY id ORDER BY ttime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS val
FROM stretch
ORDER BY id, ttime;

Но в большинстве случаев проще использовать MAX с оконным фреймом.


Таким образом, для протяжки вниз значений NULL предыдущим не NULL значением удобно использовать оконную функцию MAX с соответствующим фреймом.