我有2列电话号码,要求是获取最后8位数字相同的号码。列A的数字为11位,列B的数字为9位或10位。 我尝试使用 SUBSTR 或 Like 和向左函数来解决,但问题是数据太大,我无法使用它方式。
select trunc(ta.timeA), ta.columnA
from table1A ta,
tableB tb
WHERE substr(ta.columnA,-8) LIKE substr(tb.columnB,-8)
and trunc(ta.timeA) = trunc(ta.timeB)
AND trunc(ta.timeA) >= TO_DATE('01/01/2018', 'dd/mm/yyyy')
AND trunc(ta.timeA) < TO_DATE('01/01/2018', 'dd/mm/yyyy') + 1
GROUP BY ta.columnA, trunc(ta.timeA)
答案 0 :(得分:1)
您要从表A中进行选择,因此执行此操作。不要参加您只想选择tableB中具有匹配项的tableA行。因此,在您的EXISTS
子句中放置一个WHERE
子句。
select trunc(timea), columna
from table1a ta
where trunc(timea) >= date '2018-01-01'
and trunc(timea) < date '2018-01-02'
and exists
(
select *
from tableb tb
where trunc(tb.timeb) = trunc(ta.timea)
and substr(tb.columnb, -8) = substr(ta.columna, -8)
)
order by trunc(timea), columna;
为了快速运行,创建以下索引:
create idxa on tablea( trunc(timea), substr(columna, -8) );
create idxb on tableb( trunc(timeb), substr(columnb, -8) );
但是,我不明白为什么您如此渴望快速运行它。您是否要保留所有数据并再次运行查询?应该有一个更好的解决方案。首先想到的是将区号和数字分成两个单独的列。
更新:仍然比建议的idxa更快,它应该是tableA的覆盖索引:
create idxa on tablea( trunc(timea), substr(columna, -8), columna );
这里,DBMS只能使用索引,而不必访问表。因此,以防万一上述情况对您来说仍然太慢,您可以尝试使用更改后的索引。
正如Alex Poole在下面的评论中指出的那样,应该是
where trunc(timea) = date '2018-01-01'
仅,如果您要查看的范围始终是一天,如示例中所示。
答案 1 :(得分:0)
您可以在下面尝试使用= operator
代替like operator
您要匹配的最后两位数字
select trunc(ta.timeA),ta.columnA
from table1A ta inner join tableB tb
on substr(ta.columnA,-8) = substr(tb.columnB,-8)
and trunc(ta.timeA) = trunc(ta.timeB)
AND trunc(ta.timeA) >= TO_DATE('01/01/2018', 'dd/mm/yyyy')
AND trunc(ta.timeA) < TO_DATE('01/01/2018', 'dd/mm/yyyy') + 1
GROUP BY ta.columnA, trunc(ta.timeA)
答案 2 :(得分:0)
如果您更具体地了解您的SQL环境,将更容易获得帮助,以下是有关此查询的一些建议,这些建议适用于大多数环境。
在处理大数据集时,性能变得尤为重要,而技术上的细微变化也会产生重大影响。
例如: 像通常用于通配符的部分匹配一样,您不是说等于吗? Like慢于平等,如果您不使用通配符,我建议您寻找平等。
此外,您最初是从(叉/笛卡尔积)连接开始的,但是随后您的where子句定义了非常特定的匹配条件(匹配时间字段),如果需要匹配的时间字段,请使其成为表连接的一部分,这将减少联接结果的数量,这将大大缩小数据集,然后需要将其他条件应用于该数据集。
此外,在where子句中使用日期计算的值很慢。最好在查询之前设置一个@fromDate和@toDate参数,然后在where子句中使用这些参数,然后是不需要为每一行计算的文字。