Sql 左外部联接与嵌套聚合选择相比,在表中查找最新行有什么好处?
我正在做:Sql 左外部联接与嵌套聚合选择相比,在表中查找最新行有什么好处?,sql,oracle,Sql,Oracle,我正在做: select * from mytable y where y.year = (select max(yi.year) from mytable yi where yi.person = y.person) 从性能方面来看,这比: select y.* from mytable y left outer join mytable y2 on y.year < y2.year and y.person =
select * from mytable y
where y.year = (select max(yi.year)
from mytable yi
where yi.person = y.person)
从性能方面来看,这比:
select y.* from mytable y
left outer join mytable y2
on y.year < y2.year
and y.person = y2.person
where y2.year is null
解释计划/轶事证据是不确定的,所以我想知道一般来说,一个比另一个好。它们看起来在关系上并不等同——第一个是对第二个不在场的人进行相关子查询
select * from mytable y
where y.year = (select max(yi.year)
from mytable yi
where yi.person = y.person)
可以改写为:
select [list of columns]
from (select [list of columns including year],
max(year) over (partition by person) as max_year
from mytable)
where year = max_year
为了避免自连接。通常,两个查询都可以根据数据分布生成不同的执行计划 但是,假设您的第二个查询实际上是:
SELECT y.*
FROM mytable y
LEFT JOIN
mytable y2
ON y2.person = y.person
AND y2.year > y.year
WHERE y2.year IS NULL
,左连接版本很可能会更快,因为它将被优化为哈希反连接或带有筛选器的哈希连接,这取决于您是否有mytable person、year或not的索引以及其他一些条件。子查询版本无法优化为反联接
您可能会发现这些查询更有效:
SELECT *
FROM mytable y
WHERE (y.person , y.year) IN
(
SELECT person, MAX(year)
FROM mytable
GROUP BY
person
)
或
,第一种方法在多人和人均几年的情况下效率更高,而第二种方法在相反的情况下效率更高
你可以用行号替换密集的列号,这样你就可以在个人身上消除重复的列号,如果你愿意的话。类似于亚当的。。。据我所知,比任何使用连接的版本都要快
select *
from (select person, year, ...
Rank() over (partition by person order by year desc) as Rank
from mytable)
where Rank = 1
您确定这两个查询给出相同的结果吗?看起来他们不应该这样。我不知道,但是第一个向我表达的意图比第二个要清楚得多。你没有忘记在左侧连接的ON条件中添加y.person=y2.person吗?也许你可以发布查询计划图片?我的错误-是的,我忘记了一个连接。。。在我的测试中编辑了这个问题,如果这个人是主键,他的第一个查询将被优化为一个内部合并join@Magnus:如果person是PK,您可以将整个内容替换为SELECT*FROM mytable。如果此查询保存为视图,会发生什么情况?如果我从person=:X的视图中选择,它将执行子查询重构还是仅在生成整个数据集后应用person条件?说到这一点,我在视图中执行嵌套查询的运气好坏参半。@RenderLn:Oracle在优化时同时扩展内联视图和声明视图。如果您没有用PUSH_PRED、MATERIALIZE和类似的提示专门指示优化器,那么计划将是相同的。
select *
from (select person, year, ...
Rank() over (partition by person order by year desc) as Rank
from mytable)
where Rank = 1