这是我的(简化)问题,我猜很常见:
create table sample (client, recordDate, amount)
我想找出每个客户的最新录音,包括recordDate和amount 我制作了以下代码,但是我想知道是否有更好的模式或Oracle调整来提高这种SELECT的效率。 (我不允许修改数据库的结构,所以索引等对我来说是遥不可及的,并且超出了问题的范围)。
select client, recordDate, Amount
from sample s
inner join (select client, max(recordDate) lastDate
from sample
group by client) t on s.id = t.id and s.recordDate = t.lastDate
该表有50万条记录,选择需要2-4秒,这是可以接受的,但我很想知道是否可以改进。
由于
答案 0 :(得分:2)
在大多数情况下,窗口聚合函数可能表现更好(至少写起来更容易):
select client, recordDate, Amount
from
(
select client, recordDate, Amount,
rank() over (partition by client order by recordDate desc) as rn
from sample s
) dt
where rn = 1
答案 1 :(得分:1)
查询的另一个结构是not exists
。在某些情况下,这可以更快地执行:
select client, recordDate, Amount
from sample s
where not exists (select 1
from sample s2
where s2.client = s.client and
s2.recordDate > s.recordDate
);
这将充分利用sample(client, recordDate)
上的索引(如果有的话)。
另外,要尝试的是keep
:
select client, max(recordDate),
max(Amount) keep (dense_rank first order by recordDate desc)
from sample s
group by client;
此版本假设每个客户端只有一个最大记录日期(您的原始查询不做出此假设)。
这些查询(以及dnoeth的查询)应该都有不同的查询计划,您可能会对其中一个查询计划很幸运。但是,最好的解决方案是拥有适当的索引。