Для MySQL 8:
with recursive rcte(dt_id, col, value) as (
(
select dt_id, col, value
from mytable
order by dt_id
limit 1
)
union all
select r.dt_id + interval 1 day
, coalesce(t.col, r.col)
, coalesce(t.value, r.value)
from rcte r
left join mytable t on t.dt_id = r.dt_id + interval 1 day
where r.dt_id < (select max(dt_id) from mytable)
)
select r.col, r.dt_id, r.value
from rcte r
order by r.dt_id
db-fiddle
Рекурсивный запрос будет строить строку за строкой, увеличивая дату начиная с первой даты до последней,value
(и col
) взяты из исходной таблицы, которая оставлена объединенной в дату.Если в исходной таблице нет строки для даты, вместо нее берется значение последней строки в рекурсии.
Для более старых версий вы можете использовать таблицу календаря, а подзапрос в левой части присоединяется к ONпредложение для получения последних существующих значений:
select b.col, c.date_id, b.value
from time_table c
left join balance b on b.dt_id = (
select max(dt_id)
from balance b1
where b1.dt_id <= c.date_id
)
where c.date_id >= (select min(dt_id) from balance)
and c.date_id <= (select max(dt_id) from balance)
db-fiddle
Обновление
Поскольку вопрос изменился:
select b.col, c.date_id, b.value
from (
select col, min(dt_id) as min_dt, max(dt_id) as max_dt
from balance
group by col
) i
join time_table c
on c.date_id >= i.min_dt
and c.date_id <= i.max_dt
left join balance b
on b.col = i.col
and b.dt_id = (
select max(dt_id)
from balance b1
where b1.dt_id <= c.date_id
and b1.col = i.col
)
order by b.col, c.date_id
db-fiddle
Убедитесь, что у вас есть индекс для (col, dt_id)
.В лучшем случае это будет первичный ключ.date_id
в time_table
также следует индексировать или первичным ключом.