慢速自连接的替代方案(oracle sql)

Posted

技术标签:

【中文标题】慢速自连接的替代方案(oracle sql)【英文标题】:Alternatives to slow self join (oracle sql) 【发布时间】:2020-06-10 16:17:17 【问题描述】:

我正在自加入一个表,以便在同一行获取日期 t 和日期 t+1month 的变量“status”,分别保存为“status_a”和“status_b”:

select * from 
  (select mydate, id, status status_a from T) A
inner join 
  (select add_months(mydate,1) mydate, id, status status_b from T) B 
using(mydate, id);

我这样做是因为我需要检查一个条件,该条件涉及两个相邻时段中“状态”列的值,例如status_a in(0,2,4) and status_b in(91,93,95)。 问题在于,考虑到表 T 的大小,这个连接需要很长时间。 有没有办法以更有效的方式做同样的事情? 我考虑的可能性:

    在几个日期而不是整个表 T 上迭代连接,这可能需要 PL/SQL 语句。 可以直接在窗口函数中加入一个简单的条件;但是,由于我需要检查的条件需要考虑值是否属于值列表(例如status_a in(0,2,4) and status_b in(91,93,95)),因此可能无法使用窗口函数获得输出。如果要考虑的条件的两个日期不相邻,也不是每个 ID 的“第一个和最后一个”记录,则会出现其他复杂情况。

您有什么建议可以在 Oracle SQL 中加速这种自联接?

【问题讨论】:

您的查询没有提及状态的附加条件,因此部分问题相当不清楚。 请提供样本数据和期望的结果。可能有更简单的方法来做你想做的事。 【参考方案1】:

您可以使用带有range 规范的窗口函数。您的现有查询可以改写为:

select
    mydate,
    id,
    status status_a,
    first_value(status) over(
        partition by id
        order by mydate
        range between interval '1' month preceding and interval '1' month preceding
    ) status_b
from t

如果需要,可以直接在窗口函数中添加附加条件,例如:

first_value(case when status in (91,93,95) then status end) over(...)

但是如果没有看到实现您想要的逻辑的实际查询和/或示例数据和所需结果,就无法确定评估。

【讨论】:

以上是关于慢速自连接的替代方案(oracle sql)的主要内容,如果未能解决你的问题,请参考以下文章

oracle 嵌套查询 子查询 自连接 等值连接条件

如何使用 QThread 从慢速 Sql 语句中填充自定义 QTableWidget?

PL/SQL 的数值优化或替代方案

Java程序连接Oracle数据库时怎么设置主键自增

oracle多表查询-自连接

oracle自连接