左外连接和嵌套聚合选择有什么好处来查找表中的最新行?

aw *_*rud 2 sql oracle

我正在做:

select * from mytable y
where y.year = (select max(yi.year) 
                from mytable yi
                where yi.person = y.person)
Run Code Online (Sandbox Code Playgroud)

从性能方面来看,这是好还是坏:

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
Run Code Online (Sandbox Code Playgroud)

解释计划/轶事证据是不确定的,所以我想知道一般情况下一个是否优于另一个.

Qua*_*noi 5

"通常",两个查询都可以根据数据分布生成不同的执行计划.

但是,假设您的第二个查询实际上是这样的:

SELECT  y.*
FROM    mytable y
LEFT JOIN
        mytable y2
ON      y2.person = y.person
        AND y2.year > y.year
WHERE   y2.year IS NULL
Run Code Online (Sandbox Code Playgroud)

,LEFT JOIN版本很可能会更快,因为它将被优化为a HASH ANTI JOIN或a HASH JOINwith filter,具体取决于你是否有索引mytable (person, year)和其他条件.子查询版本无法针对反连接进行优化.

您可能最有可能发现这些查询更有效:

SELECT  *
FROM    mytable y
WHERE   (y.person , y.year) IN
        (
        SELECT  person, MAX(year)
        FROM    mytable
        GROUP BY
                person
        )
Run Code Online (Sandbox Code Playgroud)

要么

SELECT  *
FROM    (
        SELECT  y.*,
                DENSE_RANK() OVER (PARTITION BY person ORDER BY year DESC) dr
        FROM    mytable y
        )
WHERE   dr = 1
Run Code Online (Sandbox Code Playgroud)

,第一个在人数很多,每人几年的情况下更有效率,第二个在相反的情况下效率更高.

如果你想要的话,你可以DENSE_RANKROW_NUMBER它替换你可以摆脱重复person, MAX(year).