Mysql
 sql >> Database >  >> RDS >> Mysql

mysql genera date mancanti con valore precedente

Per 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

La query ricorsiva costruirà riga per riga incrementando la data a partire dalla prima data fino all'ultima. Il value (e col ) è tratto dalla tabella originale, che viene lasciata unita alla data. Se la tabella originale non ha una riga per una data, viene preso invece il valore dell'ultima riga nella ricorsione.

Per le versioni precedenti puoi utilizzare la tabella del calendario e una sottoquery nella clausola ON di join a sinistra per ottenere gli ultimi valori esistenti:

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

Aggiorna

Poiché la domanda è cambiata:

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

Assicurati di avere un indice su (col, dt_id) . Nel migliore dei casi sarebbe la chiave primaria. date_id nella time_table dovrebbe anche essere indicizzato o la chiave primaria.