2015-09-01 42 views
0

我有一個像這樣的Id,DateTime,Device,Value表。 我需要查找Value> = 5的所有期間,並返回此期間的From和To dateTime。 設備可以是一個溫度傳感器,我需要一個溫度超過5的From/To列表。SQL列表periodes其中值超過特定值

如果我們認爲它是一個溫度傳感器,並且它每5分鐘記錄一次。該表將如下:

Id DateTime   Device Value 
-------------------------------- 
1 2015.09.01 09:10 T1  3,2 
2 2015.09.01 09:15 T1  5,2 
3 2015.09.01 09:20 T1  6,2 
4 2015.09.01 09:25 T1  5,8 
5 2015.09.01 09:30 T1  3,2 
6 2015.09.01 09:35 T1  1,2 
7 2015.09.01 09:40 T1  5,6 
8 2015.09.01 09:45 T1  6,1 
9 2015.09.01 09:50 T1  5,0 
10 2015.09.01 09:55 T1  2,0 

我試圖找到的時期是從09:15到09:25和從09:40到09:50。

在SQL Server 2014中有這樣做的巧妙方法嗎?

+0

如果您可以提供一些示例數據以及所需的結果集,將會有所幫助。 –

+0

我不確定從哪裏開始。我想我必須找到所有記錄值> = 5,然後我必須找到最後一個記錄,其中值大於等於5,但是其中沒有任何記錄與情人值。 –

+0

如果我們認爲它是一個溫度傳感器,並且它每5分鐘記錄一次。 tabel會是這樣的。 1. 2015.09.01 09:10 T1 3,2 2. 2015.09.01 09:15 T1 5,2 3. 2015.09.01 09:20 T1 6,2 4. 2015.09.01 09:25 T1 5 ,8 5. 2015.09.01 09:30 T1 3,2 6. 2015.09.01 09:35 T1 1,2 7. 2015.09.01 09:40 T1 5,6 8. 2015.09.01 09:45 T1 6,1 9. 2015.09.01 09:50 T1 5,0 10. 2015.09。01 09:55 T1 2,0 我試圖找到的periodes然後是從09:15到09:25和從09:40到09:50。 –

回答

2

這是獲得所需結果的方式:

SELECT MIN([DateTime]) AS StartPeriod, MAX([DateTime]) AS EndPeriod, 
     Device 
FROM (  
SELECT Id, [DateTime], Device, Value, 
     ROW_NUMBER() OVER (PARTITION BY Device ORDER BY Id) - 
     COUNT(CASE WHEN Value >= 5 THEN 1 END) 
     OVER (PARTITION BY Device ORDER BY Id) AS grp 
FROM mytable) AS t 
WHERE t.Value >= 5 
GROUP BY Device, grp 

,如果你想獲得Start您可能需要PARTITION BY Device, [DateTime] - 每天End週期。

Demo here

+0

謝謝,Giorgos Betsos :) –

0

是的,有一個明智的做法。

查看'PARTITION BY'和'OVER'子句。

使用這些功能,我相信你應該能夠對期間的數據進行分區(分組),並獲得每個組的DateTime列的MIN和MAX值。

0

這基本已經answered before的訣竅就在於,你必須不斷地連續有序id列了。如果這不存在,你需要做更多的前期工作,以減少適當的工作。

select * into #tempTable from (
select Id = 1,[DateTime] = cast('2015.09.01 09:10' as datetime), device = 'T1', value = 3.2 
union all select 2,cast('2015.09.01 09:15' as datetime),'T1',5.2 
union all select 3,cast('2015.09.01 09:20' as datetime),'T1',6.2 
union all select 4,cast('2015.09.01 09:25' as datetime),'T1',5.8 
union all select 5,cast('2015.09.01 09:30' as datetime),'T1',3.2 
union all select 6,cast('2015.09.01 09:35' as datetime),'T1',1.2 
union all select 7,cast('2015.09.01 09:40' as datetime),'T1',5.6 
union all select 8,cast('2015.09.01 09:45' as datetime),'T1',6.1 
union all select 9,cast('2015.09.01 09:50' as datetime),'T1',5 
union all select 10,cast('2015.09.01 09:55' as datetime),'T1',2) A 


with T as (select *, row_number() over (order by id) - id as grp 
    from #tempTable 
    where value >=5 
    ) 
select [to] = min(T.Datetime), [from] = max(T.DateTime) 
from T 
group by T.grp 
order by T.grp 

與輸出是

to      from 
2015-09-01 09:40:00.000 2015-09-01 09:50:00.000 
2015-09-01 09:15:00.000 2015-09-01 09:25:00.000 

(我不得不做一些鑄造,讓您的數字/日期格式爲我工作)

0

我一直在使用一個表用戶定義的函數該參數需要一天的時間,並且該函數中的光標允許填充返回的表格,如下所示:

CREATE TABLE sensor (id int not null identity(1,1) primary key, 
    measureDate datetime, sensor nvarchar(10), measure float) 

INSERT sensor (measureDate, sensor, measure) VALUES 
('2015-09-01 09:10', 'T1', '3.2'), ('2015-09-01 09:15', 'T1', '5.2'), 
('2015-09-01 09:20', 'T1', '6.2'), ('2015-09-01 09:25', 'T1', '5.8'), 
('2015-09-01 09:30', 'T1', '3.2'), ('2015-09-01 09:35', 'T1', '1.2'), 
('2015-09-01 09:40', 'T1', '5.6'), ('2015-09-01 09:45', 'T1', '6.1'), 
('2015-09-01 09:50', 'T1', '5.0'), ('2015-09-01 09:55', 'T1', '2.0') 
GO 
CREATE FUNCTION [dbo].[getTimeSpansBelowMaxTemp] (@measureDate date) 
    RETURNS @timeSpans TABLE (fromTime time, toTime time) AS BEGIN 

    DECLARE @measure float, @currentMeasure float = NULL 
    DECLARE @measureTime time, @fromMeasureTime time, @toMeasureTime time 
    DECLARE yourCursor CURSOR FOR 
    SELECT CAST(measureDate AS time), measure 
     FROM sensor 
      WHERE CAST(measureDate as date) = @measureDate 
    OPEN yourCursor 
    FETCH NEXT FROM yourCursor INTO @measureTime, @measure 
    WHILE (@@FETCH_STATUS = 0) BEGIN -- Loops on all the measures of the given day 
     IF @measure >= 5.0 BEGIN 
       IF @currentMeasure IS NULL BEGIN -- Start of a period 
        SET @currentMeasure = @measure 
        SET @fromMeasureTime = @measureTime 
       END 
       SET @toMeasureTime = @measureTime 
     END 
     ELSE BEGIN 
       IF @currentMeasure IS NOT NULL BEGIN -- End of a period 
        INSERT INTO @timeSpans VALUES (@fromMeasureTime, @toMeasureTime) 
        SET @currentMeasure = NULL 
       END 
     END 
     FETCH NEXT FROM yourCursor INTO @measureTime, @measure 
    END 

    CLOSE yourCursor 
    DEALLOCATE yourCursor 

    RETURN 
END 
GO 

select * from dbo.[getTimeSpansBelowMaxTemp]('2015-09-01')