2009-12-06 74 views
2

我有一個大表(數百萬行),我需要根據存在的某個列值以及未發生指定的「超時」的位置。我認爲一種方法是在整個表格中找到發生這些「超時」差距的地方。如何在給定列在指定時間間隔內沒有特定值的時間排序表中找到間隙

示例表:

 
+----------------+------+ 
| time   | base | 
+----------------+------+ 
| 1245184797.064 | a | 
| 1245184802.020 | a | 
| 1245184807.103 | b | 
| 1245184812.089 | b | 
| 1245184816.831 | b | 
| 1245184821.856 | a | 
| 1245184821.856 | a | 
| 1245184855.903 | a | 
| 1245184855.903 | b | 
| 1245184858.362 | b | 
| 1245184858.362 | b | 
| 1245184860.360 | a | 
| 1245184860.360 | a | 
| 1245184862.174 | a | 
| 1245184862.174 | b | 
| 1245185001.480 | b | 
| 1245185417.556 | a | 
| 1245185417.844 | a | 
| 1245185419.960 | b | 
| 1245185420.181 | b | 
+----------------+------+ 

鑑於這一集,我將如何快速找到未發生的幾秒鐘內給定基數=一個表中的點(比如說5)。

爲了解決這個問題,我的目標是在沒有超時的情況下一致地找到base = HAS發生的記錄跨度。

回答

3

我認爲這將有助於你:

SELECT * FROM (
    SELECT t1.[time], 
      t1.time - (SELECT MAX(time) FROM my_table t2 WHERE t2.time < t1.time and t2.base = 'a') AS timeout 
    FROM my_table t1 
    WHERE t1.base = 'a') d 
WHERE timeout > 5 

而且不要忘了此查詢創建索引以更有效:

CREATE INDEX idx_my_table_time_base ON my_table (time, base) 
+0

+1 Works,刪除'WHERE t1.base ='a''並用''替換't2.base ='a''' t2.base = t1.base',使它搜索所有的基本差距 – Andomar

+0

是的。在任何情況下都使用t2.base = t1.base。 –

+0

同樣有趣的是,時間與上述類似,對於具有3000行的基礎,時間爲6秒。您的建議索引也未被優化器選中。還是太慢了。 –

0

一種方式來處理,這是檢查「伸展頭」,即從最後一次出現以來超過5秒的基數的發生。這個例子查詢聯接表上本身過濾掉非頭:

select head.* 
from  @t head 
left join @t nohead 
on  head.base = nohead.base 
and  head.time - 5 < nohead.time and nohead.time < head.time 
where  nohead.base is null 
order by head.[time] 

對於每一行,left join搜索最後5秒內相同的基礎。 where nohead.base is null子句說這樣的行可能不存在。效果是當沒有基地的情況下發生5秒以上的跨度時的列表。

它不會列出最近的差距:你能明確增加「結束時間」行對每個基地:

<end time>  a 
<end time>  b 
... 

使查詢檢查結束隙。

+0

有趣的解決方案,但它仍然需要太多的時間 - 6秒查詢3000行的基地。 –

+0

@naturalethic:我會說在(基礎,時間)上添加一個索引...但對於3000行,6秒的速度太慢了,即使你沒有定義任何索引。 – Andomar

1

一種可能性,如果你使用的是支持窗/分析功能的數據庫是這樣的:

select * from (
    select time, 
      base, 
      time - lag(time) over(partition by base order by time) as interval 
    from example) w 
where w.interval > 5 

這應該能夠從(基地,時間)指數的單次掃描工作。它適用於PostgreSQL 8.4,我認爲它也可以在SQL Server 2008和Oracle 10上工作。

相關問題