2013-07-28 29 views
1

我想畫一個簡單(讀:快)的空白火花的灌漿時間序列數據摘要

的數據是非常簡單的「從傳感器接收每ň分鐘數據」,它是一個或多個讀數,對於給定的時間戳,由傳感器的MAC地址識別:

# SELECT mac, ants, read_at FROM normalized_readings LIMIT 10; 
     mac  | ants |   read_at 
-------------------+------+------------------------- 
f0:d1:a9:a0:fe:e7 | -87 | 2013-07-14 09:25:15.215 
74:de:2b:fa:ca:cf | -69 | 2013-07-14 09:25:14.81 
74:de:2b:fa:ca:cf | -69 | 2013-07-14 09:25:14.81 
74:de:2b:fa:ca:cf | -69 | 2013-07-14 09:25:15.247 
38:aa:3c:8f:a0:4f | -85 | 2013-07-14 09:25:21.672 
38:aa:3c:8f:a0:4f | -87 | 2013-07-14 09:25:21.695 
60:67:20:c8:bc:80 | -83 | 2013-07-14 09:25:26.73 
60:67:20:c8:bc:80 | -81 | 2013-07-14 09:25:26.737 
f0:d1:a9:a0:fe:e7 | -83 | 2013-07-14 09:25:36.207 
f0:d1:a9:a0:fe:e7 | -91 | 2013-07-14 09:26:07.77 
(10 rows) 

我試圖想出這樣的:

# SELECT 
    mac, date_trunc('minute', read_at) AS minute, COUNT(*) 
    FROM 
    normalized_readings 
    GROUP BY mac, minute LIMIT 10; 
     mac  |  minute  | count 
-------------------+---------------------+------- 
00:08:ca:e6:a1:86 | 2013-07-14 16:22:00 |  6 
00:10:20:56:7c:e2 | 2013-07-27 05:29:00 |  1 
00:21:5c:1c:df:7d | 2013-07-14 09:44:00 |  1 
00:21:5c:1c:df:7d | 2013-07-14 09:46:00 |  1 
00:21:5c:1c:df:7d | 2013-07-14 09:48:00 |  1 
00:24:d7:b3:31:04 | 2013-07-15 06:51:00 |  1 
00:24:d7:b3:31:04 | 2013-07-15 06:53:00 |  3 
00:24:d7:b3:31:04 | 2013-07-15 06:59:00 |  3 
00:24:d7:b3:31:04 | 2013-07-15 07:02:00 |  3 
00:24:d7:b3:31:04 | 2013-07-15 07:06:00 |  3 
(10 rows) 

但是請注意所有的空白時段,我希望能夠提取0這段時間以表示傳感器未記錄數據。

也許我只會想顯示過去12/24小時的數據,所以我想我可以通過從NOW() 12/24小時選擇人造日期過去,併爲每個人分辨率(可能是1分鐘或5分鐘),我不得不查詢讀數表,並計算讀數的數量,但這聽起來可怕的低效率。

有沒有一種方法可以做到我想要做的事情,而不是蠻橫的東西?據我所知,當我通過選擇分鐘進行分組時,我會自動從錯誤的方面進行分析?

回答

1

對於此類查詢,您需要一個可生成「mac」和「minutes」所有組合的驅動程序表。 Postgres有很好的功能generate_series()每分鐘得到一個計數器。

所以,這個想法是從所有的Mac開始,併爲每一分鐘生成一個系列。然後使用驅動程序表中的left outer join爲每個值獲取一行。

with t as (
     SELECT mac, date_trunc('minute', read_at) AS minute, COUNT(*) as cnt 
     FROM normalized_readings 
     GROUP BY mac, minute 
     LIMIT 10 
    ) 
select driver.mac, driver.minute, coalesce(cnt, 0) 
from (select mac, minminute, 
      minminute + cast(cast(generate_series(0, 
                cast(extract(epoch from maxminute - minminute)/60 as int) 
               ) as character varying 
           )||' minute' as interval 
          ) as minute 
     from (select mac, min(minute) as minminute, max(minute) as maxminute 
      from t 
      group by mac 
      ) macs 
    ) driver left outer join 
    t 
    on t.mac = driver.mac and 
     t.minute = driver.minute 

SQL小提琴是here

我能看到的唯一問題是如何獲得原始數據 - t的定義。我跟着問題中的例子。但是,這實際上並不合理。你有一個limit沒有order by。您應該輸入合適的order by

+0

謝謝Gordon,他們應該用'mac,read_at'命令。我投擲了一個任意的「LIMIT 10」,爲了不殺死50萬個條目,但是你是對的。沒有'ORDER BY'的'LIMIT'確實沒有意義。 –