0

我有这样的表

create table #tmp(dt Date, price float)

insert into #tmp values('01-Jan-2013', 55.60)
insert into #tmp values('02-Jan-2013', 50.22)
insert into #tmp values('03-Jan-2013', 52.00)
insert into #tmp values('04-Jan-2013', 55.90)
insert into #tmp values('05-Jan-2013', 60.60)

select * from #tmp order by dt
drop table #tmp

我想在一个 SQL 语句中获得两天价格的返回值。计算很简单,例如,如果我想计算 Date 02-Jan-2013 的返回值是:2013 年 1 月 2 日的价格值除以 2013 年 1 月 1 日的价格值和 -1。

我想要一个像下面这样的输出

dt          |price  |Return
-------------------------------------
01-Jan-2013 |55.6   |0
-------------------------------------
02-Jan-2013 |50.22  |-0.09676259
-------------------------------------
03-Jan-2013 |52     |0.035444046
-------------------------------------
04-Jan-2013 |55.9   |0.075
-------------------------------------
05-Jan-2013 |60.6   |0.084078712

如何在单个 SQL 语句中获得结果?

4

1 回答 1

2

看起来相当简单:

select
   t1.dt,t1.price,
  (t1.price/t2.price)-1 as [return]
from
   #tmp t1
      left join
   #tmp t2
      on t1.dt = DATEADD(day,1,t2.dt)

请注意,这当前返回NULL第一行而不是0,但如果需要,可以通过将计算包装在 a 中来解决此问题COALESCE(...,0)。另请注意,这假设每天都有值。如果不是这样,我们需要一个更复杂的查询。


如果您需要允许缺少日期,您将不得不为显着变慢的查询付出代价:

select
   t1.dt,t1.price,
  (t1.price/t2.price)-1 as [return]
from
   #tmp t1
      left join
   #tmp t2
      on t2.dt < t1.dt
      left join
   #tmp t3
      on t3.dt < t1.dt and
         t2.dt < t3.dt
where
   t3.dt is null

暂时忽略所有这些行都来自同一个表,我们基本上所说的是将t1行与行之前出现的任何 行配对。然后,我们尝试(通过)查找出现在行之后但仍在行之前的任何行。只有当我们找不到一行时,我们想要的行才是我们想要的行——它是最新的可能的上一行。抱歉,如果这听起来令人费解,一直在寻找更好的方法来解释这一点。t2t1t3t2t1t3t2

于 2013-06-13T07:37:02.550 回答