两个查询:
select tbraccd_pidm,
max(tbraccd_balance)
keep (dense_rank first order by tbraccd_tran_number)
over (partition by tbraccd_pidm)
from tbraccd;
select tbraccd_pidm, tbraccd_balance
from tbraccd a
where tbraccd_tran_number = (select max(tbraccd_tran_number)
from tbraccd b
where b.tbraccd_pidm = a.tbraccd_pidm);
他们的自动跟踪:
PK_TBRACCD
是 TBRACCD_PIDM
和 TBRACCD_TRAN_NUMBER
的索引。
根据 V$Stats,第一次查询使用 2.43x CPU 来完成第一次调用而不是第二次调用,并且在 DB 时间上的差异大致相同。
他们使用相同的索引,并且每个人都在执行 FULL SCAN。为什么第二个功能表现得更好?
第一个查询:
select tbraccd_pidm,
max(tbraccd_balance)
keep (dense_rank first order by tbraccd_tran_number)
over (partition by tbraccd_pidm)
from tbraccd;
将返回表中的所有行;您在
SELECT
子句中找到最大值,但它未在 WHERE
子句中用于过滤结果集,因此您返回每一行。
这也是不同的,因为您使用的是
DENSE_RANK FIRST
,它找到最小值,而不是 DENSE_RANK LAST
(或 DENSE_RANK FIRST ORDER BY ... DESC
)来找到最大值。
比较:
select tbraccd_pidm, tbraccd_balance
from tbraccd a
where tbraccd_tran_number = (select max(tbraccd_tran_number)
from tbraccd b
where b.tbraccd_pidm = a.tbraccd_pidm);
有一个
WHERE
子句,查询只需要返回结果的一个子集。
如果您希望查询等效,那么第一个查询应该是:
SELECT tbraccd_pidm,
tbraccd_balance
FROM (
SELECT tbraccd_pidm,
tbraccd_balance,
RANK() OVER (partition by tbraccd_pidm ORDER BY tbraccd_tran_number) AS rnk
FROM tbraccd
)
WHERE rnk = 1;
或
SELECT tbraccd_pidm,
tbraccd_balance
FROM (
select tbraccd_pidm,
tbraccd_balance,
tbraccd_tran_number,
MAX(tbraccd_tran_number) OVER (partition by tbraccd_pidm) AS max_number
from tbraccd
)
WHERE tbraccd_tran_number = max_number;