Вернуть строки, которые были недавно обновлены в данный день - PullRequest
0 голосов
/ 31 октября 2011

Я застрял в своем запросе SQL / Oracle ..

Для этого вопроса интересующие поля: effective_day (td.ws_date), ot.valid_from и ot.valid_to.

Для каждого effective_day возвращается одна запись. Запись действительна до тех пор, пока она была отредактирована до или после effective_day и до или после effective_day. Чтобы узнать, когда он действовал, мы смотрим на поля ot.valid_from и ot.valid_to.

ot.valid_from <= effective_day <= ot.valid_to

order_no может обновляться несколько раз в течение одного дня - поля valid_to и valid_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, тогда должен быть возвращен идентификатор 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 голосов
/ 31 октября 2011

Используйте подзапрос в предложении 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))
0 голосов
/ 31 октября 2011

Самый простой способ справиться с valid_from и valid_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, так что может потребоваться некоторая корректировка.

0 голосов
/ 31 октября 2011

Чтобы избежать подобных проблем, используйте будущую дату (например, 31-DEC-9999) в качестве даты начала действия для текущей активной / действительной записи.

Таким образом, вы всегда можете использовать between(), чтобы найти последнюю запись. Также ORDER BY будет вести себя правильно.

Если вы не можете изменить это, создайте представление, которое заменит null выбранной вами датой:

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