Oracle - как обновить уникальную строку на основе максимальной даты вступления в силу, которая является частью уникального индекса - PullRequest
0 голосов
/ 27 мая 2020

Oracle - Допустим, у вас есть таблица с уникальным ключом для имени, ssn и даты вступления в силу. Дата вступления в силу делает его уникальным. Как лучше всего обновить текущий индикатор, чтобы он отображал неактивные строки с датами меньше максимальной даты вступления в силу? Я не могу осмыслить это, так как есть несколько строк с одинаковыми именами и комбинациями ssn. Мне не удалось найти здесь этот сценарий для Oracle, и у меня есть блок разработчика. Спасибо.

Ответы [ 2 ]

0 голосов
/ 27 мая 2020

Используйте оператор MERGE с помощью функции analyti c, чтобы идентифицировать строки для обновления, а затем объединить в псевдостолбце ROWID, чтобы Oracle мог эффективно идентифицировать строки для обновления (без необходимости выполнять дорогостоящее самосоединение путем сравнения значений):

MERGE INTO table_name dst
USING (
  SELECT rid,
         max_eff_date
  FROM   (
    SELECT ROWID AS rid,
           effective_date,
           status,
           MAX( effective_date ) OVER ( PARTITION BY name, ssn ) AS max_eff_date
    FROM   table_name
  )
  WHERE ( effective_date < max_eff_date AND status <> 'inactive' )
  OR    ( effective_date = max_eff_date AND status <> 'active' )

) src
ON ( dst.ROWID = src.rid )
WHEN MATCHED THEN
  UPDATE
  SET status = CASE
               WHEN src.max_eff_date = dst.effective_date 
               THEN 'active'
               ELSE 'inactive'
               END;

Итак, для некоторых образцов данных:

CREATE TABLE table_name ( name, ssn, effective_date, status ) AS
SELECT 'aaa', 1, DATE '2020-01-01', 'inactive' FROM DUAL UNION ALL
SELECT 'aaa', 1, DATE '2020-01-02', 'inactive' FROM DUAL UNION ALL
SELECT 'aaa', 1, DATE '2020-01-03', 'inactive' FROM DUAL UNION ALL
SELECT 'bbb', 2, DATE '2020-01-01', 'active'   FROM DUAL UNION ALL
SELECT 'bbb', 2, DATE '2020-01-02', 'inactive' FROM DUAL UNION ALL
SELECT 'bbb', 3, DATE '2020-01-01', 'inactive' FROM DUAL UNION ALL
SELECT 'bbb', 3, DATE '2020-01-03', 'active'   FROM DUAL;

Запрос обновляет только 3 строки, которые необходимо изменить, и:

SELECT *
FROM   table_name;

Выходы:

NAME | SSN | EFFECTIVE_DATE | STATUS  
:--- | --: | :------------- | :-------
aaa  |   1 | 01-JAN-20      | inactive
aaa  |   1 | 02-JAN-20      | inactive
aaa  |   1 | 03-JAN-20      | active  
bbb  |   2 | 01-JAN-20      | inactive
bbb  |   2 | 02-JAN-20      | active  
bbb  |   3 | 01-JAN-20      | inactive
bbb  |   3 | 03-JAN-20      | active  

db <> fiddle здесь

0 голосов
/ 27 мая 2020

"Все имена / ssn имеют максимальную дату вступления в силу раньше, чем это время вчера:"

SELECT name, ssn
FROM t
GROUP BY name, ssn
HAVING MAX(eff_date) < SYSDATE - 1

Oracle поддерживает несколько столбцов в, поэтому

UPDATE t
SET current_indicator = 'inactive'
WHERE (name,ssn,eff_date) IN (
  SELECT name, ssn, max(eff_date)
  FROM t
  GROUP BY name, ssn
  HAVING MAX(eff_date) < SYSDATE - 1
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...