前两行与多行之间的差异

时间:2017-10-20 08:57:22

标签: sql-server sql-server-2008 tsql

我有两张桌子

tblStation

StationId | TPTagId
1         |  7
2         |  8
3         |  9

tblValues

DateAndTime              | TPTagId | Val
2017-01-01 13:00:00.000  |   7     | 500
2017-01-01 13:15:00.000  |   7     | 700
2017-01-01 13:30:00.000  |   7     | 750  
2017-01-01 13:23:00.000  |   8     | 610
2017-01-01 13:24:00.000  |   8     | 630
2017-01-01 13:25:00.000  |   8     | 640
2017-01-01 13:49:00.000  |   9     | 888
2017-01-01 13:49:30.000  |   9     | 890
2017-01-01 13:49:45.000  |   9     | 901

tblStation中的TagId显示其值存储在tblValues中的位置。

我希望找到每个电台按日期降序排序的前两个值之间的差异。

所以在上面的例子中我的结果集是:

结果

StationId |  Difference
1         |  50
2         |  10
3         |  11

是否可以在单个查询中执行此操作?

值表上没有主键,所以我认为这意味着我无法进行自我加入?

到目前为止,我有这个,它通过StationId和DateAndTime降序获取所有站点及其值。但我不知道如何区分每组前两名

select s.StationID, v.DateAndTime, v.Val
from dbo.tblValues v
inner join dbo.tblStation s on s.TPTagId = v.TPTagId
group by s.StationId, v.DateAndTime, v.Val
order by s.StationId, v.DateAndTime desc

1 个答案:

答案 0 :(得分:3)

可以使用窗口函数完成:

Create table #values ([DateAndTime] datetime, [TPTagId] int, [Val] int)

insert into #values values ('2017-01-01 13:00:00.000', 7, 500)
insert into #values values ('2017-01-01 13:15:00.000', 7, 700)
insert into #values values ('2017-01-01 13:30:00.000', 7, 750)  
insert into #values values ('2017-01-01 13:23:00.000', 8, 610)
insert into #values values ('2017-01-01 13:24:00.000', 8, 630)
insert into #values values ('2017-01-01 13:25:00.000', 8, 640)
insert into #values values ('2017-01-01 13:49:00.000', 9, 888)
insert into #values values ('2017-01-01 13:49:30.000', 9, 890)
insert into #values values ('2017-01-01 13:49:45.000', 9, 901)

;with Last_Dates as 
(
Select distinct TPTagId
    , First_Value([DateAndTime]) OVER (Partition by [TPTagId] order by [DateAndTime] Desc) as [DateAndTime]
    , First_Value([Val]) OVER (Partition by [TPTagId] order by [DateAndTime] Desc) as [Val]
from #values
),
Last_but_one_dates as
(
Select distinct v.TPTagId
    , First_Value(v.[Val]) OVER (Partition by v.[TPTagId] order by v.[DateAndTime] Desc) as [Val]
from #values v
left join Last_Dates ld on ld.TPTagId = v.TPTagId and ld.[DateAndTime] = v.[DateAndTime]
where ld.TPTagId is null
)
Select ld.[TPTagId] as StationID, abs(ld.[Val] - lb1.[Val]) as [Difference]
from Last_dates ld
inner join Last_but_one_dates lb1 on ld.[TPTagId] = lb1.[TPTagId]