Oracle: выбрать строку на основе указанной даты - PullRequest
0 голосов
/ 31 января 2019

У меня есть данные ниже:

WITH  T AS (
SELECT 333 "ID",TO_DATE('2015/04/01','yyyy/mm/dd') "DT",331 AS VAL1,'GG' AS VAL2 FROM DUAL
UNION ALL 
SELECT 444 "ID",TO_DATE('2012/05/10','yyyy/mm/dd') "DT",441 AS VAL1,'AA' AS VAL2 FROM DUAL
UNION ALL 
SELECT 444 "ID",TO_DATE('2013/03/01','yyyy/mm/dd') "DT",442 AS VAL1,'AA1' AS VAL2 FROM DUAL
UNION ALL 
SELECT 444 "ID",TO_DATE('2018/08/12','yyyy/mm/dd') "DT",443 AS VAL1,'AA1' AS VAL2 FROM DUAL
UNION ALL
SELECT 555 "ID",TO_DATE('2012/05/10','yyyy/mm/dd') "DT",551 AS VAL1,'AA' AS VAL2 FROM DUAL
UNION ALL 
SELECT 555 "ID",TO_DATE('2017/03/01','yyyy/mm/dd') "DT",552 AS VAL1,'BB1' AS VAL2 FROM DUAL
UNION ALL 
SELECT 555 "ID",TO_DATE('2018/03/01','yyyy/mm/dd') "DT",553 AS VAL1,'GGGA1' AS VAL2 FROM DUAL
UNION ALL
SELECT 555 "ID",TO_DATE('2018/09/12','yyyy/mm/dd') "DT",554 AS VAL1,'JJBB1' AS VAL2 FROM DUAL
UNION ALL 
SELECT 555 "ID",TO_DATE('2019/10/09','yyyy/mm/dd') "DT",555 AS VAL1,'OOOUA1' AS VAL2 FROM DUAL
UNION ALL 
SELECT 666 "ID",TO_DATE('2012/05/10','yyyy/mm/dd') "DT",441 AS VAL1,'AA' AS VAL2 
FROM DUAL
UNION ALL 
SELECT 666 "ID",TO_DATE('2013/03/01','yyyy/mm/dd') "DT",442 AS VAL1,'AA1' AS VAL2 
FROM DUAL
UNION ALL 
SELECT 666 "ID",TO_DATE('2016/08/12','yyyy/mm/dd') "DT",443 AS VAL1,'AA1' AS VAL2 
FROM DUAL
)
SELECT * FROM (
SELECT id,val1 ,val2,dt
      ,ROW_NUMBER() OVER(PARTITION BY id ORDER BY dt ASC) rnk
  FROM T
);

        ID       VAL1 VAL2   DT               RNK
---------- ---------- ------ --------- ----------
       333        331 GG     01-APR-15          1
       444        441 AA     10-MAY-12          1
       444        442 AA1    01-MAR-13          2
       444        443 AA1    12-AUG-18          3
       555        551 AA     10-MAY-12          1
       555        552 BB1    01-MAR-17          2
       555        553 GGGA1  01-MAR-18          3
       555        554 JJBB1  12-SEP-18          4
       555        555 OOOUA1 09-OCT-19          5   

Здесь мне нужно выбрать запись на основе даты ввода.

Пример: INPUT_DATE = '17 -DEC-2016 '

Сценарии:

  1. Если идентификатор имеет только одну запись, выберитеэта одна запись -Простая
  2. Если идентификатор имеет несколько записей, выберите запись, где "INPUT_DATE" больше, чем столбец "DT", а затем выберите МИНИМАЛЬНУЮ дату

Так ожидается Выход:

        ID       VAL1 VAL2   DT               RNK
---------- ---------- ------ --------- ----------
       333        331 GG     01-APR-15          1
       444        443 AA1    12-AUG-18          3
       555        552 BB1    01-MAR-17          2

Ответы [ 3 ]

0 голосов
/ 31 января 2019

Следующие запросы должны работать для обоих ваших сценариев.

Версия, которая возвращает 2 записи для идентификаторов, которые имеют неуникальный dt.

SELECT * FROM t MyT
WHERE dt = (
    SELECT MIN(DT) FROM t
    WHERE id = t.id AND dt >= INPUT_DATE
)

Версия, которая будет всегда возвращать 1 запись (запись, которую она выберет для хранения, является "случайной")

SELECT *
FROM (
    SELECT *, row_number() OVER (PARTITION BY id ORDER BY dt) AS MyRank FROM T
    WHERE dt >= INPUT_DATE
) MyT
WHERE MyRank = 1

Вы также можете получить тот же результат, что и 1-й запрос, взяв 2-й запрос и изменив row_number() на rank().Это действительно о синтаксисе, который вы предпочитаете в тот момент.

0 голосов
/ 31 января 2019

Вы бы сделали:

select t.*
from (select t.*,
             row_number() over (partition by id,
                                order by (case when dt >= INPUT_DT then 1 else 2 end), dt asc
                               ) as seqnum
      from t
     ) t
where seqnum = 1;
0 голосов
/ 31 января 2019

У меня нет базы данных Oracle, поэтому это не точный код, но вы можете попробовать что-то вроде ниже.

 select * from test where val1 in(
 select val1 from test  where dt in 
 (select max(DT) from test where DT>INPUT_DATE group by val1))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...