2009-05-23 143 views
2

可以說我有一個表格,其中包含一個充滿記錄的時間戳列,我想用一個查詢來計算兩個連續記錄之間的最小時間差。如何計算連續事件之間的最短時間?

也許表像...

CREATE TABLE `temperatures` (
    `temperature` double, 
    `time` timestamp DEFAULT CURRENT_TIMESTAMP 
); 

回答

3

假設在第E時間戳記(以防止出現在同一時間在兩個錄音):

SELECT MIN(timediff(t1.`time`, t2.`time`)) AS delta_t, 
    FROM temperatures t1 JOIN temperatures t2 ON t1.`time` < t2.`time` 

這回答了問題,而恰恰 - 並沒有傳達其它有用信息(如這兩個時間戳或溫度)。在支持子查詢以及分貝---

0

你可以試試這個:

SELECT 
    T1.*, 
    (SELECT MIN(T2.time) 
    FROM temperatures T2 
    WHERE T2.time > T1.time)-T1.time diff 
FROM 
    temperatures T1 
ORDER BY 
    T1.time 
+0

正常工作需要在MySQL年齡約10,000行:( 對`diff`產生奇怪的值進行測試,如-20090500997993 – araqnid 2009-05-23 13:11:53

2

嘗試這樣的查詢:

select 
    cur.timestamp as CurrentTime, 
    prev.timestamp as PreviousTime, 
    timediff(cur.timestamp,prev.timestamp) as TimeDifference, 
    cur.temperature - prev.temperature as TemperatureDifference 
from temperatures cur 
left join temperatures prev on prev.timestamp < cur.timestamp 
left join temperatures inbetween 
    on prev.timestamp < inbetween.timestamp 
    and inbetween.timestamp < cur.timestamp 
where inbetween.timestamp is null 

第一個加入尋求所有以前的行爲當前(「當前」)行。第二個連接在第一行和第二行之間尋找行。 where語句表示在第一行和第二行之間不能有任何行。這樣,你就可以得到一行行的列表。

+0

這將活像,但會很慢,並且不能正確處理重複時間戳 – Quassnoi 2009-05-23 17:03:14

+0

您是否需要將MIN()函數應用於時間差和相應的GROUP BY子句?您不需要檢查是否存在間隔因爲如果有的話,第一個和第二個之間的時間差會小於第一個和第三個之間的時間差,因此MIN()會擺脫它。在其他情況下,您必須確保沒有中間讀數在當前和以前之間,並且這使事情變得複雜化無法結束。 – 2009-05-23 17:05:10

+0

@Jonathan:有一個加入與INBETWEEN這個檢查。 – Quassnoi 2009-05-23 17:16:35

4

你需要的是分析功能LAGMIN

它們在MySQL中丟失,但可以使用會話變量輕鬆模擬。

該查詢返回的連續記錄之間的所有差異:

SELECT (temperature - @r) AS diff, 
     @r := temperature 
FROM (
     SELECT @r := 0 
     ) vars, 
     temperatures 
ORDER BY 
     time 

這個方法返回最小的時間差:

SELECT (
     SELECT id, 
       @m := LEAST(@m, TIMEDIFF(time, @r)) AS mindiff, 
       @r := time 
     FROM (
       SELECT @m := INTERVAL 100 YEAR, 
         @r := NULL 
       ) vars, 
       temperatures 
     ORDER BY 
       time, id 
     ) qo 
WHERE qo.id = 
     (
     SELECT id 
     FROM temperatures 
     ORDER BY 
       time DESC, id DESC 
     LIMIT 1 
     ) 

看到這篇文章在我的博客上如何仿效MySQL分析功能:

如果添加PRIMARY KEY你表(!你應該永遠,永遠做),那麼你可以使用更SQL -ish解決方案:

SELECT temperature - 
     (
     SELECT temperature 
     FROM temperatures ti 
     WHERE (ti.timestamp, ti.id) < (to.timestamp, to.id) 
     ORDER BY 
       ti.timestamp DESC, ti.id DESC 
     LIMIT 1 
     ) 
FROM temperatures to 
ORDER BY 
     to.timestamp, to.id 

該解決方案,雖然是在相當低效MySQL由於bug 20111

子查詢不會使用range訪問路徑,但它將使用(timestamp,id)上的索引進行排序。

根據當前記錄的id,可以通過創建返回先前溫度的UDF解決此問題。

有關詳細信息,請參閱本文中我的博客:

如果你不使用任何過濾條件,則它使用會話變量的解決方案將是最有效的,但MySQL具體。

SQL Server類似的解決方案將是這樣的:

SELECT temperature - 
     (
     SELECT TOP 1 temperature 
     FROM temperatures ti 
     WHERE ti.timestamp < to.timestamp 
       OR (ti.timestamp = to.timestamp AND ti.id < to.id) 
     ORDER BY 
       ti.timestamp DESC, ti.id DESC 
     ) 
FROM temperatures to 
ORDER BY 
     to.timestamp, to.id 

SELECT MIN(mindiff) 
FROM (
     SELECT timestamp - 
       (
       SELECT TOP 1 timestamp 
       FROM temperatures ti 
       WHERE ti.timestamp < to.timestamp 
         OR (ti.timestamp = to.timestamp AND ti.id < to.id) 
       ORDER BY 
         ti.timestamp DESC, ti.id DESC 
       ) AS mindiff 
     FROM temperatures to 
     ORDER BY 
       to.timestamp, to.id 
     ) q 

SQL Server,這將工作OK,只要你有(timestamp, id)指數(或只是(timestamp),如果你的PRIMARY KEY被聚集)