В общем, отвечу другим юношам, обдумывающим житьё.
select m_date, id_tool, m_close
-- вот так получаю предыдущее значение, там, где текущее значение равно NULL
, COALESCE(m_close, LAG(m_close) OVER (PARTITION BY id_tool ORDER BY m_date)) AS m_close
from
(
SELECT distinct s.m_date, t.id_tool, null as m_close -- вот так добавляю несуществущие данные в запрос
FROM tbl_snap s
CROSS join tbl_tool t on t.is_trade = 1 and t.id_tool_type = 1
WHERE m_date not in (
SELECT m_date
FROM tbl_tool t
join tbl_snap s on s.id_tool = t.id_tool
WHERE t.id_tool_type = 1
)
UNION all -- все остальные данные
select m_date, id_tool, m_close
from tbl_snap s
)
ORDER by m_date desc, id_tool
У этого запроса есть один недостаток. Если два дня подряд не было торгов, то LAG не вернет данные, будет NULL.
Избавиться от этой проблемы можно подзапросом, вместо LAG - (
SELECT m_close
FROM tbl_snap s2
WHERE s2.id_tool = s.id_tool
AND s2.m_date < s.m_date
ORDER BY s2.m_date DESC
LIMIT 1
) m_close - однако это существенно увеличит время выполнения