Как вывести как старую, так и новую вейл в один ряд в oracle sql? - PullRequest
0 голосов
/ 12 сентября 2018

Создать таблицу запроса

CREATE TABLE ID_TAB (
    ID VARCHAR2(20),
    ID_VALUE VARCHAR2(20), FLAG VARCHAR2(20)
);

CREATE TABLE FACT_TABLE (
    ID VARCHAR2(20),
    VALUE VARCHAR2(20),
    NAME VARCHAR2(100)
);

Вставить запрос

INSERT INTO ID_TAB VALUES('100','ABC','N');
INSERT INTO ID_TAB VALUES('120','ABC','Y');

INSERT INTO FACT_TABLE VALUES('100','MAX','ORANGE');

Моя цель - обновить столбец «ID» таблицы фактов до 120, поскольку он имеет значение FLAG как «Y»

В моей исходной таблице 50 миллионов записей.

Как мы можем написать запрос в слиянии или с помощью обновления?

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Чтобы получить эффективное решение (т.е. полностью избежать объединения), вы можете переключиться на динамический SQL.

Я немного расширил ваш пример, чтобы иметь больше обновленных ключей следующим образом.

Примечаниечто существует максимум одно новое значение на ID_VALUE, но допускается более старое значение с флагом N, все из которых должны быть обновлены.

INSERT INTO ID_TAB VALUES('100','ABC','N'); -- old key
INSERT INTO ID_TAB VALUES('110','ABC','N'); -- old key
INSERT INTO ID_TAB VALUES('120','ABC','Y'); -- new key
INSERT INTO ID_TAB VALUES('200','EFG','N'); -- old key
INSERT INTO ID_TAB VALUES('210','EFG','N'); -- old key
INSERT INTO ID_TAB VALUES('220','EFG','Y'); -- new key


INSERT INTO FACT_TABLE VALUES('100','MAX','ORANGE');
INSERT INTO FACT_TABLE VALUES('110','MIN','ORANGE');
INSERT INTO FACT_TABLE VALUES('200','MAX','APPLE');
INSERT INTO FACT_TABLE VALUES('210','MIN','APPLE');
INSERT INTO FACT_TABLE VALUES('220','NEW','APPLE');
commit;

Операторы UPDATE отражают все опции eupdate,например, ключи 100 и 110 должны быть связаны с 200.

Это приводит к следующему обновлению

update FACT_TABLE
set ID = case 
when ID in ('100','110') then '200'
when ID in ('200','210') then '220' 
end
where ID in ('100','110','200','210');

Обратите внимание, что условие where состоит из всех ключей с флагом N иcase statement создается для ID_VALUE отображения всех ключей с флагом N на (только один) ключ с флагом Y.

Это делает генерацию оператора UPDATE простой и легкой задачей:запрос к столу ID_TAB.Смотрите запрос ниже.Для создания списка используется функция LISTAGG.Основные части закомментированы в запросе.

with old_keys as (
select  /* get list of all old values */
listagg(''''||ID||'''',',') within  group (order by ID) old_keys
from  ID_TAB where flag = 'N'),
case_stmt as (
select ID_VALUE,
listagg(case when flag = 'N' then ''''||ID||'''' end,',') within  group (order by ID) old_keys,
max(''''||case when flag = 'Y' then ID end||'''')  new_key
from  ID_TAB  
group by ID_VALUE),
case_stmt2 as (
select 
'when ID in ('||OLD_KEYS ||') then ' ||NEW_KEY ||' /* update for '|| ID_VALUE || ' */' case_when, ID_VALUE
from case_stmt),
case_stmt3 as ( /* concatenate CASE WHEN */
select listagg(CASE_WHEN,chr(13)) within  group (order by ID_VALUE) case_when from case_stmt2)
select 
'update FACT_TABLE
set ID = case 
'||
case_when ||
'
end
where ID in ('||
(select old_keys from old_keys)||')' as update_stmt
from case_stmt3

В примерах данных эта строка SQL возвращается

update FACT_TABLE
set ID = case 
when ID in ('100','110') then '120' /* update for ABC */
when ID in ('200','210') then '220' /* update for EFG */
end
where ID in ('100','110','200','210')
0 голосов
/ 12 сентября 2018

Вы можете попробовать следующее (хотя я этого не пробовал):

UPDATE fact_table
   SET fact_table.id = (SELECT yes_tab.id
                          FROM id_tab no_tab
                          JOIN id_tab yes_tab
                            ON no_tab.id_value = yes_tab.id_value
                           AND yes_tab.flag = 'Y'
                         WHERE no_tab.id = fact_table.id)
 WHERE EXISTS (SELECT *
               FROM   id_tab
               WHERE  id_tab.id = fact_table.id
                 AND  id_tab.flag = 'N');

WHERE EXISTS гарантирует, что вы обновляете только элементы с флагом в соответствующем ID_TAB, установленном в 'N'.
Запрос для SET выполняет поиск идентификатора соответствующего элемента с флагом, установленным в «Y».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...