Использование сопоставления с образцом для таблиц внешнего соединения в Oracle SQL - PullRequest
2 голосов
/ 20 марта 2020

Я создаю модель данных в Oracle Fusion Financials для согласования сторон, от использования поставщика и использования клиентом. Эти стороны имеют код, который зарегистрирован на их имя. Поиск по именам таблиц в Google найдет схемы (например, HZ_PARTIES ), хотя для решения этой проблемы не обязательно видеть схемы.

Качество наших данных не совсем то, что мы хотим, чтобы это было. Чтобы убедиться, что я не пропускаю записи, мне нужно присоединиться к другим сторонам, у которых также есть код в названии.

Это то, что у меня есть, что дает результаты.

SELECT
 RCTA.TRX_NUMBER
,RCTA.CT_REFERENCE 
,HP.PARTY_NAME  PARTY_NAME1
,HP2.PARTY_NAME PARTY_NAME2
,IEBC.IBAN CUSTOMER_IBAN

FROM
 HZ_PARTIES HP,
 HZ_PARTIES HP2,
 IBY_ACCOUNT_OWNERS IAO,
 IBY_EXT_BANK_ACCOUNTS IEBC,
 RA_CUSTOMER_TRX_ALL RCTA,
 HZ_CUST_ACCOUNTS HCA 

WHERE 1=1
  AND RCTA.BILL_TO_CUSTOMER_ID = HCA.CUST_ACCOUNT_ID (+)
  AND HCA.PARTY_ID = HP.PARTY_ID(+)
  AND REGEXP_SUBSTR(HP.PARTY_NAME,'([0-9]{2}[A-Z]{2}[0-9]{3})') in REGEXP_SUBSTR(HP2.PARTY_NAME,'([0-9]{2}[A-Z]{2}[0-9]{3})') -- Join on code found in party name.  
  AND IAO.ACCOUNT_OWNER_PARTY_ID (+) IN (HP2.PARTY_ID)
  AND IAO.EXT_BANK_ACCOUNT_ID = IEBC.EXT_BANK_ACCOUNT_ID (+)

Однако это выполняет внутреннее соединение вместо внешнего соединения, которое мне нужно.

Я пробовал следующее, что дает синтаксическую ошибку (отсутствует скобка):

AND REGEXP_SUBSTR(HP.PARTY_NAME,'([0-9]{2}[A-Z]{2}[0-9]{3})') = REGEXP_SUBSTR(HP2.PARTY_NAME,'([0-9]{2}[A-Z]{2}[0-9]{3})') (+)

Также попробовал это, что заставляет запрос выполняться слишком долго. Не дождался результатов, потому что он, вероятно, неверен:

AND ( REGEXP_SUBSTR(HP.PARTY_NAME,'([0-9]{2}[A-Z]{2}[0-9]{3})') = REGEXP_SUBSTR(HP2.PARTY_NAME,'([0-9]{2}[A-Z]{2}[0-9]{3})') (+) -- Join on investor code found in party name.  
   OR NOT REGEXP_LIKE(HP.PARTY_NAME,'([0-9]{2}[A-Z]{2}[0-9]{3})') -- Escape to outer join in case there's no investor code in name
  )

Если необходимо выполнить эту работу, я готов переписать (+) объединения в обычный синтаксис внешнего соединения.

Ответы [ 2 ]

1 голос
/ 20 марта 2020

Вы поместили оператор внешнего соединения (+) в неправильное место. Должно быть что-то вроде этого:

SQL> with
  2  hp (party_name) as
  3    (select '11AA111' from dual union all
  4     select '22BB222' from dual
  5    ),
  6  hp2 (party_name) as
  7    (select '11AA111' from dual union all
  8     select '33CC333' from dual
  9    )
 10  select hp.*
 11  from hp, hp2
 12  where regexp_substr(hp.party_name     , '([0-9]{2}[A-Z]{2}[0-9]{3})') =
 13        regexp_substr(hp2.party_name (+), '([0-9]{2}[A-Z]{2}[0-9]{3})')
 14  /                                  ---
                                        here
PARTY_N
-------
11AA111
22BB222

SQL>

Что касается правильных объединений ... ну, да - вы можете переписать это, если хотите, но я не думаю, что это поможет в этом случае. Если запрос выполняется нормально как , я бы оставил как и переписал бы его при необходимости.

0 голосов
/ 20 марта 2020

Я предлагаю вам добавить виртуальный столбец в таблицу hz_parties и проиндексировать его, если вам разрешено:

alter table hz_parties add code varchar2(7) as regexp_substr(party_name, '([0-9]{2}[A-Z]{2}[0-9]{3})');
create index idx_parties_code on hz_parties (code);

Если вам не разрешено изменять таблицу, используйте индекс функции вместо этого:

create index idx_parties_code on hz_parties (regexp_substr(party_name, '([0-9]{2}[A-Z]{2}[0-9]{3})'));

Если вам не разрешено добавлять индекс для существующей таблицы, то создайте новую таблицу с индексом, например:

create table party_code
(
  party_id  number(10)   not null,
  code      varchar2(7)  not null,
  primary key (party_id)
);

insert into party_code (party_id, code)
select party_id, regexp_substr(party_name, '([0-9]{2}[A-Z]{2}[0-9]{3})')
from hz_parties;

create index idx_party_code on party_code (code, party_id);

В любом из этих случаев у вас есть предварительно извлеченный код, и соединение должно быть быстрым.

Чтобы найти дубликаты, просто сгруппируйте код. Например:

select code, listagg(party_id, ', ') within group (order by party_id)
from party_code
group by code
having count(*) > 1;

Перепишите свой запрос, чтобы в любом случае использовать явные объединения, чтобы сделать его читаемым, исправить ошибочные внешние объединения и обнаружить возможные другие ошибки.

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