慢速自连接的替代方案(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)的主要内容,如果未能解决你的问题,请参考以下文章