Трудно точно следовать тому, что вы ищете, и ваши данные и результаты местами кажутся противоречивыми; Я думаю, что вы хотите использовать аналитические функции для получения последнего состояния каждого заказа, но только если последнее изменение в заказе было за последние три дня - с точностью до миллисекунды?
Использование CTE для генерации данных образца:
with orders as (
select 1 as order_id, 'pizza' as order_name, '20-feb-2012' as order_date
from dual
union all select 2, 'burger', '17-feb-2012' from dual
),
order_state as (
select 1 as order_id, 'initiated' as order_state, '20-feb-2012' as
order_state_date, '12:29:11:203' as order_state_time from dual
union all select 1, 'processed', '21-feb-2012', '12:29:12:112' from dual
union all select 1, 'cancelled', '21-feb-2012', '12:29:11:311' from dual
union all select 2, 'initiated', '17-feb-2012', '12:11:10:201' from dual
union all select 2, 'processed', '18-feb-2012', '12:01:01:301' from dual
union all select 2, 'cancelled', '19-feb-2012', '12:29:59:300' from dual
)
-- actual query starts here
select order_id, order_state, order_state_date, order_state_time
from (
select o.order_id,
first_value(os.order_state)
over (partition by os.order_id
order by os.order_state_timestamp desc) as order_state,
to_char(max(os.order_state_timestamp) over (partition by os.order_id),
'DD-mon-YYYY') as order_state_date,
to_char(max(os.order_state_timestamp) over (partition by os.order_id),
'HH24:MI:SS:FF3') as order_state_time,
max(os.order_state_timestamp) over (partition by os.order_id)
as last_order_state_timestamp,
row_number() over (partition by os.order_id order by os.order_id) as rn
from orders o
join (select order_id, order_state,
to_timestamp(order_state_date ||' '|| order_state_time,
'DD-mon-YYYY HH24:MI:SS:FF3') as order_state_timestamp
from order_state) os
on os.order_id = o.order_id
)
where rn = 1
and last_order_state_timestamp > systimestamp - interval '3' day;
ORDER_ID ORDER_STA ORDER_STATE_DATE ORDER_STATE_TIME
---------- --------- -------------------- ------------------
1 processed 21-feb-2012 12:29:12:112
Ваши ожидаемые результаты имеют cancelled
, но значения даты / времени для штатов выглядят неверно.
Если вы хотите показать заказы, созданные за последние три дня, а не только те, которые были обновлены, то вам нужно получить min()
вместо max()
отметку времени и отфильтровать ее.
Похоже, вас не интересует исправление модели для использования правильных типов столбцов даты / времени, так что это, очевидно, не имеет значения ...
Хранение даты и времени в отдельных полях делает это намного сложнее, чем нужно, и я не могу придумать какой-либо веской причины для этого. Если это сделано только потому, что поле DATE
не содержит миллисекунд, используйте вместо этого поле TIMESTAMP
. Я пытался минимизировать боль, преобразовав ее на лету в подзапросе, но это все еще не очень хорошая модель. Если у вас есть одно поле order_state_timestamp
вместо отдельных полей даты / времени, запрос может выглядеть примерно так:
select order_id, order_state,
to_char(last_order_state_timestamp, 'DD-mon-YYYY HH24:MI:SS:FF3')
as order_state_timestamp
from (
select o.order_id,
first_value(os.order_state)
over (partition by os.order_id
order by os.order_state_timestamp desc) as order_state,
max(os.order_state_timestamp) over (partition by os.order_id)
as last_order_state_timestamp,
row_number() over (partition by os.order_id order by os.order_id) as rn
from orders o
join order_state os on os.order_id = o.order_id
)
where rn = 1
and last_order_state_timestamp > systimestamp - interval '3' day;
что немного менее неприятно.
Редактировать: Исходя из комментария к вашему предыдущему / повторному вопросу , вы хотите, чтобы количество дней, которые вы оглядываетесь назад, варьировалось в зависимости от текущего дня. Это не очевидно из любого вопроса. Вы можете сделать это с помощью:
and last_order_state_timestamp > systimestamp
- numtodsinterval(decode(to_char(sysdate, 'D'), '1', 3, 1), 'DAY');
Но вы должны быть осторожны с настройками NLS; результат to_char(sysdate, 'D')
в понедельник здесь 1
, но может быть 0
или что-то еще там, где вы находитесь. См. this , особенно комментарий к элементу D
.