Я пытаюсь выбрать самую последнюю строку (процентная ставка IntRate) на основе двух дат. Дата наивысшего приоритета - EffDate, а вторая - LastMaintenance. EffDate имеет дату вступления в силу IntRate. Итак, формат выглядит примерно так: MM/DD/YYYY. В столбце LastMaintenance указано время последнего изменения строки в формате SYSDATE.

Например, если я изменю IntRate в течение одного дня, я получу две строки в таблице истории. У обоих будут одинаковые EffDate, но разные LastMaintenance даты.

Прямо сейчас я пытаюсь выбрать самые последние IntRate на основе таблицы, имеющей историю IntRate для данного аккаунта. Итак, я хочу выбрать самый последний IntRate по дате. Ближайший к этой дате IntRate - это то, что я хочу использовать.

Проблема в том, что я не могу понять, как выбрать самый последний IntRate, когда EffDate то же самое, но DateLastMaintenance другое.

На рисунке ниже, как выбрать IntRate, где значение равно null? Я хочу это, потому что, хотя EffDate то же самое, поле DateLastMaintenance новее для значения null.

Example

У меня есть что-то вроде этого, чтобы получить самый последний EffDate для данного AcctNbr и дату, когда мне нужно самое последнее значение.

SELECT EffDate
    FROM (SELECT *
    FROM AcctRateHist X
    WHERE X.AcctNbr = A.AcctNbr -- R.Acctnbr
    AND X.EffDate <= TO_DATE('09-26-2017', 'MM-DD-YYYY') -- The date to get the most recent value for
    ORDER BY X.EffDate DESC, X.DateLastMaint DESC)
WHERE ROWNUM = 1;

Это даст мне EffDate от 14.09.2017, но когда я подключаю его к внешнему запросу, я получаю все строки с EffDate от 14.09.2017, поэтому мне нужно посмотрите на столбец DateLastMaintenance сейчас.

Я попытался выбрать ROWNUM = 1, но он получил IntRate 0,0375, а не значение null (где ROWNUM = 2, я не понимаю, почему он выбирает вверх тот ..).

SELECT R.AcctNbr, X.EffDate, X.IntRate, X.InactiveDate, X.DateLastMaint
FROM AcctRateHist X, Rpt_Sort_Process R
WHERE X.AcctNbr = R.AcctNbr -- Just some stuff thats needed to get the AcctNbr: Ignore
AND R.QueNbr = somenum -- Just some stuff thats needed to get the AcctNbr: Ignore
AND R.ApplNbr = somenum -- Just some stuff thats needed to get the AcctNbr: Ignore
AND R.QueSubNbr = somenum -- Just some stuff thats needed to get the AcctNbr: Ignore
AND X.EffDate = (SELECT EffDate -- This gets the EffDate of 9/14/2017
                FROM (SELECT *
                        FROM AcctRateHist X
                        WHERE X.AcctNbr = A.AcctNbr -- R.Acctnbr
                        AND X.EffDate <= TO_DATE('09-26-2017', 'MM-DD-YYYY') -- The date to get the most recent value for
                        ORDER BY X.EffDate DESC, X.DateLastMaint DESC)
                WHERE ROWNUM = 1)
AND ROWNUM = 1 -- This SHOULD return the IntRate of null, but doesn't
ORDER BY X.EffDate DESC, X.Datelastmaint DESC;
1
Jimenemex 12 Мар 2018 в 23:18

2 ответа

Лучший ответ

Думаю, вы хотите использовать кортежи:

(X.EffDate, X.DateLastMaint) =
    (SELECT EffDate, DateLastMaint -- This gets the EffDate of 9/14/2017
     FROM (SELECT *
           FROM AcctRateHist X
           WHERE X.AcctNbr = A.AcctNbr AND
                 X.EffDate <= DATE '2017-09-26' -- The date to get the most recent value for
           ORDER BY X.EffDate DESC, X.DateLastMaint DESC)
     WHERE ROWNUM = 1
    )
1
Gordon Linoff 12 Мар 2018 в 20:28

Оконные функции идеально подходят для этой задачи. Вот пример DENSE_RANK.

create table acctratehist ( acctnbr int, intrate number (9,3), effdate date, datelastmaint timestamp);

insert into acctratehist values (89, 2.125, DATE '2018-03-11', TIMESTAMP '2018-03-11 11:00:00');
insert into acctratehist values (89, 2.375, DATE '2018-03-11', TIMESTAMP '2018-03-11 15:00:00');
insert into acctratehist values (89, 2.825, DATE '2018-03-12', TIMESTAMP '2018-03-12 13:00:00');
insert into acctratehist values (52, 2.000, DATE '2018-03-11', TIMESTAMP '2018-03-11 15:00:00');
insert into acctratehist values (52, 2.333, DATE '2018-03-12', TIMESTAMP '2018-03-12 13:00:00');

select t.acctnbr, t.effdate, t.intrate
from (
  select acctnbr, intrate, effdate, dense_rank() over (partition by acctnbr, effdate order by datelastmaint desc) as dlmrank
  from acctratehist
) t
where t.dlmrank = 1
order by t.acctnbr, t.effdate

SQLFiddle

1
Michael O'Neill 12 Мар 2018 в 20:56