Прежде всего вы храните дату и время отдельно, что делает работу с датой и временем более сложной, чем необходимо.
Один способ объединить два:
local_date + interval '1' second * (to_number(substr(time, 5, 2)) +
to_number(substr(time, 3, 2)) * 60 +
to_number(substr(time, 1, 2)) * 3600)
Другой :
to_date(to_char(local_date, 'yyyymmdd') || time, 'yyyymmddhh24miss')
С этим датой и временем вы хотите что-то вроде
where the_time >= timestamp '2019-12-01 23:00:00' and the_time < date '2019-12-03'
Для какой-то еще неизвестной даты, которая будет предоставлена при выполнении запроса:
where the_time >= :date - interval '1' hour and the_time < :date + interval '1' day
Для текущего дня, предположим, что в таблице нет будущих данных:
where the_time >= trunc(sysdate) - interval '1' hour
Что касается предпочтения более текущей даты-времени, чем более старой, используйте оконную функцию, например, MAX OVER
.
with rows_with_datetime as
(
select
mytable.*,
to_date(to_char(local_date, 'yyyymmdd') || time, 'yyyymmddhh24miss') as dt
from mytable
)
, two_days_with_maxdatetime as
(
select
rows_with_datetime.*,
max(dt) over (partition by product_id order by dt) as max_dt
from rows_with_datetime
where dt >= trunc(sysdate) - interval '1' hour
)
select *
from two_days_with_maxdatetime
where dt = max_dt
order by product_id;
Поскольку вычисляется дата и время, здесь индекс не будет использоваться, и запрос может быть довольно медленным. Таким образом, вам лучше изменить модель данных, чтобы иметь дату и время, которые можно легко индексировать и использовать вместо отдельных даты и времени. Если вы не можете, вы можете применить дополнительное избыточное условие только на одну дату:
where local_date >= trunc(sysdate) - interval '1' day