返回最近在给定日期更新的行

时间:2011-10-31 15:06:20

标签: sql oracle datetime max

我坚持使用我的SQL / Oracle查询..

对于此问题,感兴趣的字段为effective_day(td.ws_date),ot.valid_fromot.valid_to.

每个effective_day都会返回一条记录。只要在effective_day之前或之后以及effective_day之后或之后编辑该记录,该记录就有效。 要了解它何时有效,我们会查看字段ot.valid_fromot.valid_to.

ot.valid_from <= effective_day <= ot.valid_to

order_no可以在一天内多次更新 - valid_tovalid_from字段会相应更新。所以三天内一个订单的更新可能是这样的:

ID |Order   | Valid From         | Valid To           |
=================================================================
0  |112     | 07-SEP-11 21:13:12 | 08-SEP-11 01:02:11 |
1  |112     | 08-SEP-11 01:02:12 | 08-SEP-11 01:14:12 |
2  |112     | 08-SEP-11 01:14:13 | 09-SEP-11 05:23:51 |
3  |112     | 09-SEP-11 05:23:52 | 09-SEP-11 16:21:13 |
4  |112     | 09-SEP-11 16:21:14 | null               |

如果我想退回effective_day = 08-SEP-11的订单。返回的数据应该是当天最近更新的数据。所以它应该是ID 2。

同样,如果我想返回effective_day = 09-SEP-11的订单明细,则应返回ID 4.

这是我的SQL

SELECT  
  td.ws_date effective_date,
  ot.ORDER_NO,
  ot.PROCESS_AREA,
  ot.VALID_FROM,
  ot.VALID_UNTIL
  FROM ws_tracker_dates_tab td, ws_tracker_old_tab ot 
  WHERE (ot.VALID_FROM  <= td.WS_DATE)
  AND (ot.VALID_UNTIL IS NULL or (ot.VALID_UNTIL>=td.ws_date))
  AND ot.COMPLETED = 'N'
  AND td.WS_DATE BETWEEN (SYSDATE -30) AND (SYSDATE)
  AND ot.process_area is not null

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:0)

为避免此类问题,请使用将来的日期(如31-DEC-9999)作为当前有效/有效条目的“有效期”。

这样,您始终可以使用between()找到最新条目。此外ORDER BY也会正常运作。

如果您无法更改此设置,请创建一个视图,将null替换为您选择的日期:

select ..., coalesce(valid_to, to_timestamp('31-DEC-9999', 'DD-MON-YYYY')), ....

答案 1 :(得分:0)

在where子句中使用子查询,如下所示

Where ot.ID = 
    (select max(in1.ID) 
    from ws_tracker_old_tab in1 where in1.Order=ot.Order 
    and in1.VALID_FROM = (select max(in2.VALID_FROM) 
                      from ws_tracker_old_tab in2 
                      where in2.Order =in1.Order 
                      and in2.VALID_FROM  <= td.WS_DATE 
                      and (in2.VALID_UNTIL IS NULL or in2.VALID_UNTIL>=td.ws_date))

如果您知道每个订单的VALID_FROM日期总是唯一的,那么您可以更简单一点:

Where ot.VALID_FROM = (select max(in1.VALID_FROM) 
                       from ws_tracker_old_tab in1 
                       where in1.Order = ot.Order 
                       and in1.VALID_FROM  <= td.WS_DATE 
                       and (in1.VALID_UNTIL IS NULL or in1.VALID_UNTIL>=td.ws_date))

答案 2 :(得分:0)

处理valid_fromvalid_to的最简单方法(尤其是考虑到valid_to可能为空[可能意味着可能意味着什么]),是忽略valid_to :因为在这种情况下,它是一个派生的值(不是通常应该存储在数据库中的东西)。

那就是说,我相信以下内容适合你:

WITH max_stamp(effective_date, order_no, stamp) as (
               SELECT a.ws_date, b.order_no, b.MAX(b.valid_from)
               FROM ws_tracker_dates_tab a
               JOIN ws_tracker_old_tab b
               ON b.valid_from < CAST((a.ws_date + INTERVAL '1' DAY) AS TIMESTAMP)
               WHERE a.ws_date BETWEEN (SYSDATE - 30) AND (SYSDATE)
               GROUP BY a.ws_date, b.order_no)
SELECT a.*, b.effective_date
FROM ws_tracker_old_tab a
JOIN max_stamp b
ON b.stamp = a.valid_from    
AND b.order_no = a.order_no    

请注意我在DB2上,并且没有使用过Oracle,因此可能需要进行一些调整。