我一直试图找到一种方法来从有序集中选择和求和本地化的最大值。 因此,给出以下有序数据:
HardwareID Timestamp Odometer
ABC123 2013-10-28 07:47:20 300
ABC123 2013-09-25 16:40:43 250
ABC123 2013-09-11 16:33:31 200
ABC123 2013-08-08 09:03:52 120
ABC123 2013-08-05 07:52:58 80
ABC123 2013-07-22 07:42:34 30
ABC123 2013-07-03 11:47:55 140
ABC123 2013-06-25 17:27:20 100
ABC123 2013-06-13 12:01:18 50
ABC123 2013-06-11 07:59:50 10
我想要一个查询来拉出并求和两个局部最大值(300 + 140):
HardwareID Odometer
ABC123 440
我已尝试this滑动窗口方法,但无法让它适用于我的方案。是否有一种解决此类问题的常用方法(循环一组并与之前的值进行比较)?
答案 0 :(得分:0)
SQL Server 2012及更高版本具有lead()
和lag()
功能,对此有很大帮助。
select HardwareId, sum(odometer)
from (select t.*,
lag(Odometer) over (partition by HardwareId order by TimeStamp) as prevo,
lead(Odometer) over (partition by HardwareId order by TimeStamp) as nexto
from table t
) t
where Odometer > coalesce(prevo, 0) and Odometer > coalesce(nexto, 0);
你可以这样做是2012年之前的版本,但语法有点麻烦。
答案 1 :(得分:0)
我为您的测试数据添加了一个顺序标识,以使这个示例更容易,但我假设您有一个主键可以利用(如果不是时间戳上的row_number也可以。)
在这个例子中,我只是加入“下一个顺序”行并评估它是否优于。如果是这样,我认为它是一个高峰,并在随后的总和中使用。
希望你可以用它来适应你。
declare @t table (Pk int identity(1,1), HardwareID varchar(10), [Timestamp] datetime, Odometer int);
insert into @t
select 'ABC123', '2013-10-28 07:47:20', 300 union all
select 'ABC123', '2013-09-25 16:40:43', 250 union all
select 'ABC123', '2013-09-11 16:33:31', 200 union all
select 'ABC123', '2013-08-08 09:03:52', 120 union all
select 'ABC123', '2013-08-05 07:52:58', 80 union all
select 'ABC123', '2013-07-22 07:42:34', 30 union all
select 'ABC123', '2013-07-03 11:47:55', 140 union all
select 'ABC123', '2013-06-25 17:27:20', 100 union all
select 'ABC123', '2013-06-13 12:01:18', 50 union all
select 'ABC123', '2013-06-11 07:59:50', 10;
--to illustrate
select a.HardwareId,
a.Odometer,
[IsAPeak] = case when a.Odometer > isnull(b.Odometer, 0) then 1 else 0 end
from @t a
left
join @t b on
a.pk = b.pk+1 and
a.HardwareId = b.HardwareId;
select a.HardwareId,
sum(case when a.Odometer > isnull(b.Odometer, 0) then a.Odometer else 0 end)
from @t a
left
join @t b on
a.pk = b.pk+1 and
a.HardwareId = b.HardwareId
group
by a.HardwareId;