根据系统日期和时间从db中检索数据

时间:2012-02-22 11:40:15

标签: sql oracle plsql

您能否提出建议或提供任何解决方案,如何解决以下问题:

订购表:

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:3​​11 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

1 个答案:

答案 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元素的评论。