2012-06-06 15 views
3

缺少時間間隔,我有以下表中包含的值從幾個不同的設備讀取,每15分鐘:查找表

ID DeviceID Date     Value 
---------------------------------------------- 
1 3   24.08.2011 00:00:00  0.51 
2 3   24.08.2011 00:15:00  2.9 
3 3   24.08.2011 00:30:00  0 
4 3   24.08.2011 00:45:00  7.1 
5 3   24.08.2011 01:00:00  1.05 
6 3   24.08.2011 03:15:00  3.8 

我想找到的所有表格中的空白,爲每一個設備,在特定月份沒有條目的地方。對於上表,結果應該是這樣的:

DeviceID StartDate    EndDate 
------------------------------------------------------- 
3   24.08.2011 01:00:00  24.08.2011 03:15:00 

該表大約有35000個設備和1億條目。

這就是我試過的;它很慢,但返回我需要的東西。但是,除了速度之外,還有另一個問題:它只能找到特定月份中設備最後一次輸入的缺失間隔;之後的任何內容都將被忽略,因此可能會錯過缺少值的額外時間間隔。

SELECT 
    t2.Date AS StartDate 
    , t1.Date AS EndDate 
FROM 
    TestTable t1 
    INNER JOIN TestTable t2 ON t1.DeviceID = t2.DeviceID 
WHERE 
    (t2.Date = (SELECT MAX(Date) FROM TestTable t3 WHERE t3.Date < t1.Date AND t3.DeviceID = t1.DeviceID) 
     AND DATEDIFF(MINUTE, t2.Date, t1.Date) > 15) 
    AND t1.DeviceID = @id 
    AND DATEPART(YEAR, t1.Date) = @year AND DATEPART(MONTH, t1.Date) = @month 
+0

你可能想看看[這](http://www.manning.com/nielsen/SampleChapter5 .pdf)其範例章節涵蓋了Itzik Ben-Gan的空白和島嶼 –

+0

@ConradFrix感謝您的鏈接。 – alex

+0

@NikolaMarkovinović謝謝你,但我自己刪除了這個問題。這是一個糟糕的問題,我設法弄清楚了自己(我也使用了'ROW_NUMBER()')。 – alex

回答

5

以下應該工作,並不會返回一個deviceid的單個記錄。

這樣做的主旨是

  • 添加ROWNUMBER每個記錄,通過Date有序和重新啓動每個DeviceID
  • 與自己聯合創建一個結果,其行由兩個原始行的組合組成。每行的列之間的關係是rownumber(+1)和DeviceID
  • 只保留那些相關的Date超過15分鐘的行。

SQL語句

;WITH t AS (
    SELECT *, rn = ROW_NUMBER() OVER (PARTITION BY DeviceID ORDER BY Date) 
    FROM TestTable 
) 
SELECT t1.DeviceID, t1.Date, t2.Date 
FROM t t1 
     INNER JOIN t t2 ON t2.DeviceID = t1.DeviceID AND t2.rn = t1.rn + 1 
WHERE DATEDIFF(MINUTE, t1.Date, t2.Date) > 15   

測試腳本

;WITH TestTable (ID, DeviceID, Date, Value) AS (
    SELECT 1, 3, '2011-08-24 00:00:00', 0.51 UNION ALL 
    SELECT 2, 3, '2011-08-24 00:15:00', 2.9 UNION ALL 
    SELECT 3, 3, '2011-08-24 00:30:00', 0 UNION ALL 
    SELECT 4, 3, '2011-08-24 00:45:00', 7.1 UNION ALL 
    SELECT 5, 3, '2011-08-24 01:00:00', 1.05 UNION ALL 
    SELECT 6, 3, '2011-08-24 03:15:00', 3.8 
) 
, t AS (
    SELECT *, rn = ROW_NUMBER() OVER (PARTITION BY DeviceID ORDER BY Date) 
    FROM TestTable 
) 
SELECT t1.DeviceID, t1.Date, t2.Date 
FROM t t1 
     INNER JOIN t t2 ON t2.DeviceID = t1.DeviceID AND t2.rn = t1.rn + 1 
WHERE DATEDIFF(MINUTE, t1.Date, t2.Date) > 15   
+0

你放棄了參數'@ id','@ year'和'@ month' –

+0

@ConradFrix - 我錯過了,但是OP肯定知道如何將適當的值添加到where子句。 –

+0

奇怪的是,它沒有返回任何關於我擁有的數據。我會仔細研究一下,看看發生了什麼。 – alex