您能否提出建议或提供任何解决方案,如何解决以下问题:
订购表:
order id order_name order_date
1 pizza 20-feb-2012
2 burger 17-feb-2012
order_state表
order_id order_state order_state_date order_state_time
1 initiated 20-feb-2012 12:29:11:203
1 processed 21-feb-2012 12:29:12:112
1 cancelled 21-feb-2012 12:29:11:311
2 initiated 17-feb-2012 12:11:10:201
2 processed 18-feb-2012 12:01:01:301
2 cancelled 19-feb-2012 12:29:59:300
如果我在星期一查询,我必须检查最后3天,即星期五,星期六和星期日。所以我能够获取第二条记录,如果我今天查询,我能够获取第一个recrod,在两种情况下取消记录我应该能够根据数据和时间获取。
在Sql下面给出了基于日期的系统日期和时间:
select decode(TRIM(to_char(SYSDATE,'Day')),'Monday','3','1') from dual
结果,如果我在星期一下午12:30或12:29:59:299查询
order_id order_state order_name order_state_date order_state_time
2 canceled burger 19-feb-2012 12:29:59:300
结果,如果我今天在12:29:10:311 P.M
查询order_id order_state order_name order_state_date order_state_time
1 canceled pizza 21-feb-2012 12:29:59:300
谢谢,
Chaitu
答案 0 :(得分:1)
很难准确地遵循您所追求的内容,而您的数据和结果似乎在某些地方相互矛盾;我想你想用analytic functions来提取每个订单的最新状态,但是只有最后一次订单更改是在过去三天内 - 降到毫秒精度?
使用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;
稍微不那么不愉快。
修改:根据您对previous/duplicate question的评论,您希望您回顾的天数因当前日期而异。从这两个问题来看,这一点都不明显。你可以用:
来做到这一点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
元素的评论。