在子查询中执行包含max-aggregate的SQL-Statement的最有效方法

时间:2015-05-01 11:37:59

标签: sql oracle

我有一个货币表和一个exchange_rate_log表。后者包含超过十亿的记录。 exchange_rate_log表包含过去几年中许多货币的交易汇率。

现在我必须为所有可用货币(以表格货币)选择给定exchange_currency和给定日期的最新有效交易汇率。

因此,如果给定的exchange_currency为“EUR”且日期为昨天。结果将在时间窗口中将所有可用货币的最新交易从“exchange_rate_log”表中的第一个可用条目返回到“EUR”,直到昨天。

以下查询显示了获得答案的可能方法。但是,给定的查询效果不佳。

SELECT cur.name, log.price, log.valid_at
FROM currency cur
JOIN exchange_rate_log log ON (cur.id = log.currency_id)
WHERE log.valid_at = (SELECT max(log2.valid_at) 
                  FROM exchange_rate_log log2 
                  WHERE log2.currency_id = cur.id 
                  AND log2.exchange_currency = ?
                  AND log2.valid_at < ?);

是否有可能通过适应性更强的查询获得相同的结果?是否可以创建索引来提高上述查询的性能?

备注:目标dbms是Oracle。

2 个答案:

答案 0 :(得分:0)

您没有标记您正在使用的DBMS,因此这是使用标准SQL中的RANK:

select *
from 
 (
   SELECT cur.name, log.price, log.valid_at,
       RANK()
       OVER (PARTITION BY cur.id
             order by valid_at DESC) as rnk
   FROM currency cur
   JOIN exchange_rate_log log on (cur.id = log.currency_id)
   WHERE log.exchange_currency = ?
     AND log.valid_at < ?
) dt
where rnk = 1; 

如果效率更高,则取决于DBMS的优化功能。

否则在原始查询中添加log.valid_at < ?条件可能会有所帮助。

答案 1 :(得分:0)

SELECT TOP 1
    cur.name, log.price, log.valid_at
FROM exchange_rate_log log
INNER JOIN currency cur
ON log.currency_id = cur.id
WHERE log.exchange_currency = ?
AND log.valid_at < ?
ORDER BY log.valid DESC;

在log.valid和log.exchange_currency上建立索引也是非常重要的,否则什么都不会使你的查询变得快速。

我还认为所提出的查询的性能类似,但我认为它略有简化。