具有多个可能连接(或连接中的条件)的 SQL 查询
Posted
技术标签:
【中文标题】具有多个可能连接(或连接中的条件)的 SQL 查询【英文标题】:SQL Query with multiple possible joins (or condition in join) 【发布时间】:2013-08-17 15:32:30 【问题描述】:我有一个问题,我必须尝试找到那些拥有未结余额的旧帐户但创建了新帐户的人。我需要通过比较 SSN 来匹配它们。问题是我们有主要联系人和其他联系人,因此每个帐户有 2 个潜在的 SSN。我需要匹配它,即使它们最初是主要的,但现在是次要的等等。
这是我的第一次尝试,我现在只是在计算连接和条件。稍后我将选择实际数据。基本上,个人表一次加入活动帐户,另一个副本加入拖欠帐户。然后根据 4 种可能的 SSN 关联方式比较对个人表的两个引用。
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 进行加密,并提供解密它们的视图。由于我必须从那个角度工作,因此需要很长时间才能解密然后进行比较。
【问题讨论】:
表是如何索引的?如果您按 ssn 和 addl_ssn 索引(每个索引单独),您可能会获得显着的加速 数据库由我们的软件供应商管理。我不确定索引是如何设置的,或者我是否可以让他们改变它。我可以检查一下。 【参考方案1】:如果您运行单独的连接然后再联合,那么您可能会遇到问题。如果同一个记录对至少满足两个条件怎么办?然后,您的结果中会出现重复项。
我相信您的第一种方法是可行的,但不要忘记您要连接四个表。如果各个表中的行数是 A、B、C、D,那么 RDBMS 将不得不检查最多 A * B * C * D 记录。如果您的数据库中有很多记录,那么这将花费很多时间。
当然,您可以通过向某些列添加索引来优化您的查询,如果它们还没有被索引,那将是一个好主意。但不要忘记,如果您为列添加索引,RDBMS 从那里读取会更快,但在那里写入会更慢。如果您的操作主要是读取(选择),那么您应该为您的列编制索引,但不要盲目,在开始之前先研究一下索引。
此外,如果您要加入四个表,personal、consumer、personal (again) 和 uncol_acct,那么您可能会执行以下操作:
编写一个查询,其中包含两个子查询,每个子查询分别命名为 t1 和 t2。第一个子查询连接个人和消费者,并将结果命名为 t1。第二个查询将使用 uncol_acct 连接第二次出现的个人,并且 where 子句将在您的第二次连接中。如前所述,您的查询将包含两个子查询,分别命名为 t1 和 t2。您的查询将连接 t1 和 t2。这样您就可以优化,因为您的主要查询将仅考虑有效 t1 和 t2 的配对。
此外,如果您的 where 子句在示例查询中位于外部,则将执行 4 维连接,并且只有在此之后才会考虑 where。这就是为什么 where 子句应该在第二个子查询中的原因,所以 where 子句将在主连接之前运行。此外,您可以在第二个子查询中创建一个子查询,以计算条件很少满足的位置。
干杯!
【讨论】:
索引由我们的软件供应商处理,我不知道是否可以让他们更改它。这是一个罕见的程序,而且对时间不敏感,因此可能不值得。我喜欢 2 个子查询的想法,我会看看它是否更快。至于重复记录,我认为这不会发生,因为两种方法的计数相同。在这种情况下,它也不是非常重要,因为有人会检查列表以试图追踪这些人。如果他们出现两次没关系。 当且仅当至少有一对满足多个连接条件的情况下,才会出现重复记录。您可以通过使用 distinct 关键字来防止这种情况。但是,我的回答中提出的解决方案阻止了这种情况,因为查询没有分区,只有连接使用子查询重新格式化以加快速度。 我尝试了子查询方法,它所用的时间几乎与没有子查询的方法一样长。实际上不到一秒钟的差异。我想我发现了这个问题。我们的软件供应商对 SSN 进行加密。我们得到一个未加密的表格视图。所以它必须在每个 SSN 上运行一个解密例程,并且需要很长时间。 只有当你的表中有很多记录时,优化才会生效。你能指定你在四个表中的每一个有多少条记录吗? 约 70,000 个人 60,000 消费者,14,000 无法收集。以上是关于具有多个可能连接(或连接中的条件)的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章