在oracle中过滤左连接的最佳方法

时间:2017-12-08 20:04:19

标签: sql oracle left-join

我正在使用4个表进行选择,其中一个表有6.7M行。在table_1中我有一些主要代码,在table_2(具有6.7M行的那个)中,我有主代码的子代码,如下所示:

SELECT t1.code, t2.subcode
FROM table_1 t1
LEFT JOIN table_2 t2
ON t2.subcode LIKE t1.code || '%' AND
substr(replace(t2.subcode, t1.code, ''), 1, 1) not in ('0', '1', '2', '3', 
'4', '5', '6', '7', '8', '9')

规则是,代码总是有一个或两个字母和一个数字(带有1,2或3位数字),子代码是相同的代码,或者代码相同+一个字母。所以,我做了这样的左连接:

$_SESSION

它有效,但是,因为Table_2有6.7M的结果,即使有2列有索引,查询(与其他2个表连接)需要6~7分钟才能解决,我需要在更短的时间内完成。 那么,有人知道如何优化这个查询吗?

2 个答案:

答案 0 :(得分:1)

仅在代码上创建table2上的索引:

create index idx_table2_code
    on table2(case when substr(code, 3, 1) between 'A' and 'Z'
                   then substr(code, 1, 2) else code
              end);

然后将其用作join

中的表达式
select t1.code, t2.subcode
from table_1 t1 left join
     table_2 t2
     on t1.code = (case when substr(code, 3, 1) between 'A' and 'Z'
                        then substr(code, 1, 2) else code
                   end);

join应该能够使用索引。

答案 1 :(得分:0)

我不喜欢在您的加入条件中使用likein。如何使用类似的东西:

SELECT t1.code, t2.subcode
  FROM table_1 t1
       LEFT JOIN table_2 t2
                 ON t2.subcode = t1.code || 'A' OR
                    t2.subcode = t1.code || 'B' OR ...

如果你只有几个子码,只有字母表的前几个字母,这样做可能要快得多。或者,你可以尝试

SELECT t1.code, t2.subcode
  FROM table_1 t1
       LEFT JOIN table_2 t2
            ON SUBSTR(t2.subcode, 0, LENGTH(t1.code)) == t1.code AND
               SUBSTR(t2.subcode, LENGTH(t1.code) + 1, LENGTH(t2.subcode)-LENGTH(t1.code)) IN ('A', 'B', 'C', 'D'...)