2013-10-15 69 views
1

我有一個控制進入門用法的sqlite表。獲取配對時差的總和

我需要奇偶時間間隔的總和,例如卡02的預期總和是(12:03 - 08:07)+(16:03 - 14:52)= 03:56 + 01:21 = 05:07

人們可以在白天自由活動,因此卡片可能會有很多條目。

Test table

表看起來是這樣的:

card_id | time 
---------------------------- 
    03 | 07:55 
    01 | 08:02 
    02 | 08:07 
    03 | 11:56 
    02 | 12:03 
    03 | 12:23 
    02 | 14:52 
    03 | 15:56 
    01 | 15:58 
    02 | 16:03 
+0

那麼如果第一個缺失,你有點塞滿了,因爲沒有辦法告訴!第二個,默認爲現在,到一天結束,跳過? –

+0

謝謝@Tony,null當條目沒有匹配對時很好,但我不知道如何編寫查詢來解決這些問題。我可以得到兩個條目之間的時間差,但這隻適用於卡上只有兩個條目的情況,並且可能存在任何條目,因爲人們可以在白天自由移動。 –

+0

是啊,只是在想,通常我會用CTE做這樣的事情,但SQLLite沒有。 –

回答

1

查詢並不難,但時間間隔處理是!

SELECT card_id, 
    TIME(1721059.5+SUM(JULIANDAY(time)*((SELECT COUNT() FROM t AS _ WHERE card_id=t.card_id AND time<t.time)%2*2-1))) 
FROM t 
GROUP BY card_id; 

工作原理:前

((SELECT COUNT() FROM t AS _ WHERE card_id=t.card_id AND time<t.time)%2*2-1)計數的所有記錄當前和返回-11

JULIANDAY(time)將時間字符串轉換爲數字量。前兩項結果的產品將返回所需的計算結果(以天爲單位)。

TIME(1721059.5+...)將返回格式正確的時間字符串。由於JULIANDAY定義和SQLite date/time functions僅在0000-01-01 00:00:00之後的日期有效,因此需要1721059.5

編輯:看@CL回答,我看到使用JULIANDAY('00:00')更優雅,然後1721059.5。但是,我保持不變,因爲它應該更好地使用函數調用。

+0

如果我理解的很好,當條目沒有匹配對時(這很好,因爲從結果中篩選出這些卡很容易),這總是會導致消極間隔。我對嗎? –

+0

是的。我不關心它,因爲它不是一個要求。 –

+0

這對我很好,因爲我必須過濾掉它們。很好的答案,謝謝! –

1

我沒有可嘗試這種一個SQLite,但這樣的事情應該工作:

CREATE TEMP TABLE card_times AS 
SELECT time FROM entries 
WHERE card_id = 2; 

SELECT SUM(strftime("%s", '2000-01-01 ' || x.time || ':00') 
     - strftime("%s", '2000-01-01 ' || y.time || ':00')) 
FROM card_times AS x INNER JOIN card_times AS y 
ON x.ROWID = y.ROWID + 1 
WHERE (x.ROWID % 2) = 0 

獲取所需卡片的時間表。加入它自己使用行ID匹配正確的配對。濾除奇數對。總結結果。

注意如果時鐘換到第二天,這將失敗。在SQLite中處理這種情況會很糟糕。您真的需要原始數據的完整日期。

這給出了幾秒鐘內的答案。我讓你研究如何在你需要的單位中得到它。

+0

空的結果集,我無法弄清楚。 我已經上傳了測試表:http://cdn.virtuosoft.eu/stackoverflow/19393071/entries.sqlite –

+0

我在我的SQLite(Windows)上試過了,它工作正常。 – Gene

+0

好的,你說得對,問題是臨時表已經存在了(它需要'card_id ='02''而不是'2',所以它是空的)。它返回18420,相當於5:07。缺點是它只計算一張卡片。謝謝,投票去了。 –

1

這將是可以計算其時間爲奇數和偶數動態,但如果我們把這個信息到表本身更容易:

ALTER TABLE MyTable ADD odd; 

UPDATE MyTable 
SET odd = (SELECT COUNT(*) % 2 
      FROM MyTable AS c 
      WHERE c.card_id = MyTable.card_id 
      AND c.time < MyTable.time); 

然後,它可以簡單地歸納時代每張卡,將該值乘以-1偶數次。 (因爲結果是一個時間差,加入julianday('00:00')需要回到一個絕對的時間值。)

SELECT card_id, 
     (SELECT TIME(SUM(julianday(time) * CASE odd WHEN 0 THEN -1 ELSE 1 END) 
        + julianday('00:00')) 
     FROM MyTable 
     WHERE card_id = cards.card_id 
     ) AS total_time 
FROM (SELECT DISTINCT card_id 
     FROM MyTable) AS cards; 

03|07:34:00 
01|07:56:00 
02|05:07:00 
+0

非常感謝您的回答,但我已經接受LS_dev,因爲它更簡單。 –