为了在一个查询中高效地获取每个货币/股票在特定日期前的最后一个报价和倒数第二个报价,并充分利用currency_id, stock_id, quote_date上的索引,可以采用递增方式完成:首先查找每个货币/股票的最大日期(这<em>将会</em>使用索引),然后找到上一个日期(同样使用索引),最后查找实际的报价:
with stock_ids(stock_id) as (
values (2),(23),(19),(41),(40),(26),(9),(43),
(22),(44),(28),(32),(30),(34),(20),(10),
(13),(17),(27),(35),(8),(29),(39),(16),
(33),(5),(36589),(25),(18),(6),(38),(37),
(3),(45),(7),(21),(46),(15),(4),(24),
(31),(36),(38423),(40313),(22561),(36787),(35770),(36600),
(35766),(42),(22567),(40581),(40569),(29528),(22896),(24760),
(40369),(40396),(40400),(40374),(36799),(1),(27863),(29659),
(40367),(27821),(24912),(36654),(21125),(22569),(22201),(23133),
(40373),(36697),(36718),(26340),(36653),(47),(34019),(36847),
(36694)
),
last_dates as (
select t.currency_id, t.stock_id, max(t.quote_date) as quote_date
from stock_ids
join end_day_quotes_AVG t on
t.currency_id=2 and
t.stock_id=stock_ids.stock_id and
t.quote_date <= '2023-01-31'
group by t.currency_id,t.stock_id
),
next_to_last_dates as (
select t.currency_id, t.stock_id, max(t.quote_date) as quote_date
from last_dates l
join end_day_quotes_AVG t on
t.currency_id=l.currency_id and
t.stock_id=l.stock_id and
t.quote_date < l.quote_date
group by t.currency_id,t.stock_id
)
select 'last' as 'when', currency_id, stock_id, quote_date, bid
from last_dates
join end_day_quotes_AVG using (currency_id, stock_id, quote_date)
union all
select 'next-to-last', currency_id, stock_id, quote_date, bid
from next_to_last_dates
join end_day_quotes_AVG using (currency_id, stock_id, quote_date)
如果你希望获取每个股票超过最近两天的更多日期的报价,很可能可以用一个递归公共表表达式(recursive common table expression, CTE)替代last_dates/next_to_last_dates部分,并添加一个表示天数的编号(限制为你想要收集的天数)。
在线演示链接