Sql 如何优化此查询?

Sql 如何优化此查询?,sql,performance,oracle,Sql,Performance,Oracle,我有桌子: ID、有效来源、数据。。。 B ID_B,ID,T1,T2,T3,日期 表A可以包含历史数据,例如在给定时间段内有效的数据 我需要从表B中选择记录,并从表A中选择表A中的拨款记录。我需要行,其中B.id=A.id_A,记录在B.date有效 select * from B, (select * from (select * from A where a.id_a = b.id and a.valid_from <= b.date order by valid_from des

我有桌子: ID、有效来源、数据。。。 B ID_B,ID,T1,T2,T3,日期

表A可以包含历史数据,例如在给定时间段内有效的数据 我需要从表B中选择记录,并从表A中选择表A中的拨款记录。我需要行,其中B.id=A.id_A,记录在B.date有效

select * 
from B, (select * from (select * from A where a.id_a = b.id and a.valid_from <= b.date order by valid_from desc) where rownum = 1)
where b.id = a.id_a

听起来你在寻找一个连接:

这不是很理想,但可能更具可读性:

select *  
from A a, B b
Where 
a.id_a = b.id 
and a.valid_from = (select max(valid_from) 
                    from A 
                    where id_a = b.id 
                    and valid_from <= b.date)
order by valid_from desc
然后您可以这样查询它:

ID Valid_from                Valid_to
1  01/01/2011 12.34.56.0000  02/01/2011 12.34.56.0000
1  02/01/2011 12.34.56.0001  03/01/2011 12.34.56.0000
1  03/01/2011 12.34.56.0001  31/12/9999 23.59.59.9999
select *  
from A a, B b
Where 
a.id_a = b.id 
and b.date between a.valid_from and a.valid_to
order by valid_from desc

在日期列上有一个索引,性能应该是可以的。

我已经接受了StevieG的答案并对其进行了扩展。如果没有有效的_to列,则需要编写复杂的子查询。我建议使用LEAD分析函数来找到当前有效期的结束点,并进行处理。这是子查询和有效的_to列的替代方法

LEAD分析函数查看当前数据集中的行,找到下一个有效的_from date,并将其用作当前期间的结束

我的查询如下所示。它将您提供的示例数据合并到with子句中

with table_a as (
  select 1 as id, 'XXX1' as data, date '2009-01-01' as valid_from from dual union all
  select 1 as id, 'XXX2' as data, date '2009-05-30' as valid_from from dual union all
  select 1 as id, 'XXX3' as data, date '2010-01-11' as valid_from from dual union all
  select 2 as id, 'YYY' as data, date '1999-01-01' as valid_from from dual
),
table_b as (
  select 1 as id, 1 as id_a, date '2009-02-01' as date_col from dual union all
  select 2 as id, 2 as id_a, date '2009-09-12' as date_col from dual union all
  select 3 as id, 1 as id_a, date '2009-06-30' as date_col from dual
)
select *
from table_b b
  join (
    select 
      id, 
      valid_from, 
      lead(valid_from, 1, date '9999-12-31') over (partition by a.id order by a.valid_from) as valid_to
    from table_a a
) a on (a.id = b.id_a)
where 
  a.valid_from <= b.date_col and 
  b.date_col < a.valid_to

也许oracle引用更合适谢谢不幸的是,我不确定你的url是否对我有帮助。问题不在于如何编写联接,而在于如何从具有历史记录的表中有效地选择特定记录。每个记录都包含一些数据和有效性字段-ValidFrom。如果你想为给定的日期选择特定的记录,你必须选择所有有效的记录。你能给我们一些示例数据吗?这样我们就可以更确切地了解你想做什么?据我所知,当你从B中得到一行时,你必须从a中得到所有日期较小的行,其中ID匹配?表a ID,数据,有效期从:1,'XXX1','01/01/2009'1,'XXX2,'05/30/2009'1,'XXX3,'01/11/2010'2,'YYY,'01/01/1999'。表B ID,ID_A,日期:1,1,'02/01/2009'2,2,'09/12/2011'3,1,'06/30/2009。我想得到1,1,'02/01/2009','XXX1';2,2、'09/12/2011'、'YYY';3,1、'06/30/2009'、'XXX2'并非所有记录都来自。。我只需要A中的一条或零条记录,其中ID匹配,并且A中的记录对B.date有效-表A包含历史记录。表A中数据的每次更改都会创建新记录,ValidFrom设置为curren_时间戳。我需要从A中选择在给定B日期有效的记录。谢谢。在Oracle上,使用valid_from=max的查询速度非常慢。当您将列ValidTo放入表中时,插入/更新速度会变慢,因为您必须找到以前的历史记录并进行更新,然后插入新的历史记录。还有其他选择和更新功能。但这可能是最好的解决方案:我同意,这要慢一点。如果插入/更新性能对您来说也是一个问题,那么您可以做我所做的事情——将非最新版本存储在单独的历史模式中。当您创建新版本时,而不是插入时,您将更新主模式中的当前记录,并触发将旧记录的副本插入历史模式。2次插入比查找+更新+插入更快…您有哪些索引以及解释计划结果是什么?数据库中的性能调优应该从这里开始,而不是重新编写查询。谢谢。是的,它很好用。Lead功能需要Oracle数据库的企业版。。。