Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 左外部联接与嵌套聚合选择相比,在表中查找最新行有什么好处?_Sql_Oracle - Fatal编程技术网

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