通过另一个值查找值

Looking up value by another value

我是 运行 SQL Server 2016,遇到以下问题,这看起来很基本,但我无法解决。我有一个 table Prices,它包含不同证券的价格,列

idTag varchar(12) NOT NULL
ts    datetime2   NOT NULL
price float       NOT NULL

我还有另一个 table DataidTagts,其中标签完全匹配,但时间戳不匹配。我想找到Datatable每一行对应的价格(相当于时间上的常数插值)

例如,Prices 中的示例值可能是

idTag | ts               | price
=================================
IBM   | 2020-01-01 13:00 | 100.23
IBM   | 2020-01-01 13:05 | 100.34
IBM   | 2020-01-01 13:10 | 100.45
IBM   | 2020-01-01 13:15 | 100.29
IBM   | 2020-01-01 13:20 | 100.31

Data table 的样本值可能是

idTag | ts
========================
IBM   | 2020-01-01 13:01
IBM   | 2020-01-01 13:03
IBM   | 2020-01-01 13:17
IBM   | 2020-01-01 13:18
IBM   | 2020-01-01 13:20

预期输出为

idTag | ts               | price
=================================
IBM   | 2020-01-01 13:01 | 100.23
IBM   | 2020-01-01 13:03 | 100.23
IBM   | 2020-01-01 13:17 | 100.29
IBM   | 2020-01-01 13:18 | 100.29
IBM   | 2020-01-01 13:20 | 100.31

如果两个 table 中的时间戳都匹配,我可以写一个 INNER JOIN,但在这里,时间戳不匹配。我也可以在代码中做到这一点,e.q。 Python 或 Java,但 Prices 有超过 1.5 亿行,我宁愿不读它。

在 SQL 中有没有办法做到这一点? 非常感谢

当然,使用解析将 ts 的下一个值复制到当前行,然后使用范围谓词:

select *
from
 (select *, lead(ts) over(partition by idtag order by ts) as nextts from prices) p 
 inner join data d
 on 
   d.idtag = p.idtag and 
   d.ts >= p.ts and
   d.ts < p.nextts
where 
  idtag = 'IBM'

可能需要一段时间才能处理数亿行..

您可以在子查询中获取某个日期的最新价格。

select
  idtag, ts,
  (
    select top(1) price
    from prices p
    where p.idtag = d.idtag
    and p.ts <= d.ts
    order by p.ts desc
  ) as price
from data d
order by idtag, ts;

(您也可以将此子查询移动到 FROM 子句并使用 CROSS APPLY)。

推荐指数:

create index idx on prices(idtag, ts, price);