0

我有两个类似的表层次结构:

Owner -> OwnerGroup -> Parent

Owner2 -> OwnerGroup2

我想根据一组值确定 Owner2 中是否存在完全匹配的所有者。每个 Owner 表中大约有 100 万行。一些 OwnerGroup 最多包含 100 个所有者。

所以基本上,如果有一个 OwnerGroup 包含所有者“Smith”、“John”和“Smith、“Jane”,我想知道完全匹配的 OwnerGroup2 的 id。

第一次尝试是为每个所有者生成一个连接(这需要在应用程序中生成动态 sql:

select og.id
from owner_group2 og
-- dynamic bit starts here
join owner2 o1 on
(og.id = o1.og_id) AND
(o1.given_names = 'JOHN' and o1.surname='SMITH')
-- dynamic bit ends here
join owner2 o2 on
(og.id = o2.og_id) AND
(o2.given_names = 'JANE' and o2.surname='SMITH');

这在少数所有者之前工作得很好,但是当我们必须在一个组场景中处理 100 个所有者时,因为这个查询计划意味着有 100 个嵌套循环,并且需要将近一分钟的时间来运行。

我的另一个选择是在操作员周围使用一些东西intersect。例如

select * from ( 
select o.surname, o.given_names
from owner1 o1
join owner_group1 og1 on o1.og_id = og1.id 
where 
og1.parent_id = 1936233
)
intersect
select o.surname, o.given_names
from owner2 o2 
join owner_group2 og2 on og2.id = o2.og_id;

我也不确定如何在这种情况下吸出 owner2.id - 而且它仍在 4-5 秒范围内运行。

我觉得我遗漏了一些明显的东西 - 所以请随时提供一些更好的解决方案!

4

1 回答 1

0

你在正确的轨道上intersect,你只需要走得更远一点。您需要将它的结果连接回owner_groups2表以查找 ID。

您可以使用该listagg函数将组转换为以逗号分隔的名称列表(注意 - 需要 11g)。然后,您可以使用这些名称列表的交集来查找匹配项并将其加入到 中的列表中owner_groups2

我在下面创建了一个简化示例,其中“Dave, Jill”是两个表中都存在的组。

create table grps (id integer, name varchar2(100));
create table grps2 (id integer, name varchar2(100));

insert into grps values (1, 'Dave');
insert into grps values(1, 'Jill');

insert into grps values (2, 'Barry');
insert into grps values(2, 'Jane');

insert into grps2 values(3, 'Dave');
insert into grps2 values(3, 'Jill');

insert into grps2 values(4, 'Barry');

with grp1 as (
 SELECT id, listagg(name, ',') within group (order by name) n 
 FROM grps
 group by id
), grp2 as (
 SELECT id, listagg(name, ',') within group (order by name) n 
 FROM grps2
 group by id
)
SELECT * FROM grp2 
where  n in (
  -- find the duplicates
  select n from grp1 
  intersect
  select n from grp2
);

请注意,这仍需要对 ; 进行全面扫描owner_groups2。我想不出一种方法可以避免这种情况。因此,您的查询可能会很慢。

于 2013-02-04T13:01:57.373 回答