在 Oracle SQL 中使用模式匹配外连接表
Using pattern matching to outer join tables in Oracle SQL
我正在 Oracle Fusion Financials 中创建一个 DataModel 来将供应商使用和客户使用的各方匹配在一起。这些政党有一个以他们的名义注册的代码。
在 Google 上搜索 table 名称将找到模式(例如 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
)
如果有必要完成这项工作,我愿意将 (+) 连接重写为常规外部连接语法。
您将外连接运算符 (+)
放在了错误的位置。应该是这样的:
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>
至于正确的连接......好吧,是的 - 如果你愿意,你可以重写它,但我认为它在这种情况下没有帮助。如果查询运行正常原样,我会原样并在必要时重写它。
我建议您在 hz_parties
table 中添加一个虚拟列并对其进行索引,如果您被允许:
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);
如果不允许更改 table,则改用函数索引:
create index idx_parties_code on hz_parties (regexp_substr(party_name, '([0-9]{2}[A-Z]{2}[0-9]{3})'));
如果不允许在现有 table 上添加索引,则创建一个带有索引的新 table,例如:
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;
重写您的查询以无论如何使用显式联接以使其可读,修复错误的外部联接并发现其他可能的错误。
我正在 Oracle Fusion Financials 中创建一个 DataModel 来将供应商使用和客户使用的各方匹配在一起。这些政党有一个以他们的名义注册的代码。 在 Google 上搜索 table 名称将找到模式(例如 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
)
如果有必要完成这项工作,我愿意将 (+) 连接重写为常规外部连接语法。
您将外连接运算符 (+)
放在了错误的位置。应该是这样的:
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>
至于正确的连接......好吧,是的 - 如果你愿意,你可以重写它,但我认为它在这种情况下没有帮助。如果查询运行正常原样,我会原样并在必要时重写它。
我建议您在 hz_parties
table 中添加一个虚拟列并对其进行索引,如果您被允许:
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);
如果不允许更改 table,则改用函数索引:
create index idx_parties_code on hz_parties (regexp_substr(party_name, '([0-9]{2}[A-Z]{2}[0-9]{3})'));
如果不允许在现有 table 上添加索引,则创建一个带有索引的新 table,例如:
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;
重写您的查询以无论如何使用显式联接以使其可读,修复错误的外部联接并发现其他可能的错误。