具有多个可能连接的SQL查询(或连接中的条件)

时间:2013-08-15 12:36:04

标签: sql oracle

我遇到一个问题,我必须尝试找到拥有未结余额的旧帐户但已创建新帐户的人。我需要通过比较SSN来匹配它们。问题是我们有主要和额外的联系人,因此每个帐户有2个潜在的SSN。我需要匹配它,即使它们最初是主要的,但现在是次要等。

这是我的第一次尝试,我现在只想计算连接和条件。我稍后会选择实际数据。基本上,个人表连接一次到活动帐户,另一个连接到拖欠帐户。然后根据SSN可能与之相关的4种可能方式来比较对个人表的两个引用。

select count(*) 
from personal pa
join consumer c 
on c.cust_nbr = pa.cust_nbr
and c.per_acct = pa.acct
join personal pu
on pu.ssn = pa.ssn
or pu.ssn = pa.addl_ssn
or pu.addl_ssn = pa.ssn
or pu.addl_ssn = pa.addl_ssn
join uncol_acct u 
on u.cust_nbr = pu.cust_nbr
and u.per_acct = pu.acct
where u.curr_bal > 0

这样可行,但需要20分钟才能运行。我发现了这个问题Is having an 'OR' in an INNER JOIN condition a bad idea?所以我尝试将其重新编写为4个查询(每个ssn组合一个)并将它们合并。这需要30分钟才能运行。

有更好的方法可以做到这一点,还是只是一个非常低效的过程,无论你怎么做?

更新:在这里玩了一些选项,以及其他一些实验我认为我发现了问题。我们的软件供应商对数据库中的SSN进行加密,并提供解密它们的视图。由于我必须从该视图开始工作,因此需要很长时间才能解密然后进行比较。

1 个答案:

答案 0 :(得分:2)

如果你运行单独的连接然后联合,那么你可能会遇到问题。如果同一记录对满足至少两个条件怎么办?那么你的结果会有重复。

我相信你的第一种方法是可行的,但不要忘记你加入了四张桌子。如果各个表中的行数是A,B,C,D,则RDBMS必须检查A * B * C * D记录的最大值。如果您的数据库中有许多记录,那么这将花费很多时间。

当然,您可以通过向某些列添加索引来优化查询,如果它们尚未编入索引,那将是一个好主意。但是不要忘记,如果向列添加索引,那么RDBMS将更快地从那里读取,但在那里写入更慢。如果您的操作主要是读取(选择),那么您应该对列进行索引,但不要盲目地在开始执行之前研究索引。

另外,如果您要加入四个表,个人,消费者,个人(再次)和uncol_acct,那么您可能会这样做:

编写一个查询,其中包含两个子查询,每个子查询分别命名为t1和t2。第一个子查询加入个人和消费者,并将结果命名为t1。第二个查询将使用uncol_acct连接第二次出现的个人,而where子句将出现在第二个连接中。如前所述,您的查询将包含两个子查询,分别名为t1和t2。您的查询将加入t1和t2。这样你就可以选择,因为你的主查询只考虑有效t1和t2的配对。

此外,如果您的where子句在示例查询中位于外部,则将执行4维连接,并且仅在此之后将考虑其中的位置。这就是为什么where子句应该在第二个子查询中,所以where子句将在主连接之前运行。此外,您可以在第二个子查询中创建子查询,以计算很少满足条件的位置。

干杯!