2013-08-02 33 views
2

假設我有一個包含一組數據點的表,每個數據點都包含一個時間戳和一個值。如果至少有N個連續記錄(按時間戳排序)高於給定值X,則我將如何編寫一個返回true的查詢(1),否則返回false(0)?超過閾值的值連續n分鐘

下做到這一點,連續3條記錄,但一般情況下無需建立一個動態查詢,並增加更多的不工作「和存在」的情況:

truncate table tblData 
insert into tblData values ('1-jul-2013 13:01:00', 64) 
insert into tblData values ('1-jul-2013 13:02:00', 13) 
insert into tblData values ('1-jul-2013 13:03:00', 7) 
insert into tblData values ('1-jul-2013 13:04:00', 17) 
insert into tblData values ('1-jul-2013 13:05:00', 7) 
insert into tblData values ('1-jul-2013 13:06:00', 18) 
insert into tblData values ('1-jul-2013 13:07:00', 9) 
insert into tblData values ('1-jul-2013 13:08:00', 20) 
insert into tblData values ('1-jul-2013 13:09:00', 12) 
insert into tblData values ('1-jul-2013 13:10:00', 21) 
insert into tblData values ('1-jul-2013 13:11:00', 22) 
insert into tblData values ('1-jul-2013 13:12:00', 3) 
insert into tblData values ('1-jul-2013 13:13:00', 22) 
insert into tblData values ('1-jul-2013 13:14:00', 20) 

declare @x as int = 10 

select count(*) 
from tblData a 
where a.dt in 
(select dt from tblData b where b.value > @x and b.dt >= a.dt and b.dt < DATEADD(minute,1,a.dt)) and exists 
(select dt from tblData b where b.value > @x and b.dt >= DATEADD(minute,1,a.dt) and b.dt < DATEADD(minute,2,a.dt)) and exists 
(select dt from tblData b where b.value > @x and b.dt >= DATEADD(minute,2,a.dt) and b.dt < DATEADD(minute,3,a.dt)) 

想法?

+0

是每個時間戳保證是對時間嗎? –

回答

3

基本上,你想要一個標誌的累計和,說明該列超過了值@x

事實證明,你可以使用row_number()的一些技巧做到這一點。使用row_number()(按時間順序)枚舉所有行。然後,枚舉所有行,按標誌分區。這些之間的差異將是一個常數,標識一組連續的行。然後,通過聚合,我們可以得到標誌爲true(或false)的連續值的最長長度:

select seqnum - seqnum_flag, count(*) 
from (select d.*, 
      row_number() over (order by dt) as seqnum, 
      row_number() over (partition by (case when val > @x then 1 else 0 end) 
           order by dt) as seqnum_flag 
     from tblData d 
    ) d 
where val > @x 
group by (seqnum - seqnum_flag); 

這將返回每個序列及其長度。這應該給你你需要的信息。

你可以看到它在SQL Fiddle上工作。

+0

我已經提出了國旗的表,但仍然不知道如何計數連續的1。偉大的查詢,謝謝。 – Dan

0

您可以使用over ... rows N preceding子句計算最後N行的最小值。例如,這將顯示1,如果該行和最後3行具有大於10的值:

select * 
,  case when min(val) over (order by dt rows 3 preceding) > 10 then 1 else 0 end 
from tblData 

Example at SQL Fiddle.

+0

。 。我不認爲SQL Server 2008支持該語法。2012年出現。 –

+0

@GordonLinoff:是的,這絕對是2012語法 – Andomar