You can use a recursive CTE to break the dates into ranges:
with recursive cte as (
select start_date as day_start,
(case when date(start_date) = date(end_date) then end_date else date(start_date) + interval 1 day end) as day_end,
end_date
from (select cast('2020-01-10 13:00:00.347' as datetime) as start_date,
cast('2020-01-12 02:00:00.347' as datetime) as end_date
) t
union all
select day_end,
(case when date(day_end) = date(end_date) then end_date else date(day_end) + interval 1 day end) as day_end,
end_date
from cte
where day_end <> end_date
)
select day_start, day_end,
timestampdiff(second, day_start, day_end) / (60 * 60)
from cte;
Here is a db<>fiddle.
EDIT:
In SQL Server, this looks like:
with cte as (
select start_date as day_start,
(case when cast(start_date as date) = cast(end_date as date) then end_date else dateadd(day, 1, cast(start_date as date)) end) as day_end,
end_date
from (select cast('2020-01-10 13:00:00.347' as datetime) as start_date,
cast('2020-01-12 02:00:00.347' as datetime) as end_date
) t
union all
select day_end,
(case when cast(day_end as date) = cast(end_date as date) then end_date else dateadd(day, 1, day_end) end) as day_end,
end_date
from cte
where day_end <> end_date
)
select day_start, day_end,
datediff(second, day_start, day_end) / (60.0 * 60)
from cte;
Here is this db<>fiddle.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…