2012-09-14 41 views
1

這與Compute dates and durations in mysql query類似,不同的是我沒有唯一的ID列來處理,並且我有樣本不是​​開始/結束點。SQL將採樣點轉換爲持續時間

作爲一個有趣的實驗,我將cron設置爲ps aux > 'date +%Y-%m-%d_%H-%M'.txt。我現在有大約250,000個「機器運行的東西」的樣本。

我想將它變成「process | cmd | start | stop」的列表。假設一個'開始'事件是這對存在的第一次,一個'停止'事件是它停止存在的第一個樣本:樣本沒有機會「丟失」或任何東西。

也就是說,進行這種轉換有什麼方法,最好使用SQL(因爲我喜歡SQL,這看起來像一個很好的挑戰)。假設pid不能重複,這是一項微不足道的任務(將所有內容放在表格中,SELECT MIN(time), MAX(time), pid GROUP BY pid)。然而,由於PID/CMD對重複(我檢查,有重複),我需要一個真正的「找到所有連續段」搜索的方法。

如果有必要,我可以做形式

Load file0 -> oldList 
ForEach fileN: 
    Load fileN ->newList 
    oldList-newList = closedN 
    newList-oldList = openedN 
    oldList=newList 

的東西,但是不是SQL而不是有趣。誰知道呢,我最終可能會得到真正的SQL數據來處理這個屬性。

我在想什麼,一個人先構建一個diff表,然後加入所有的close對所有open並在每次打開後拉最小距離close,但我想知道是否有更好的方法。

回答

1

你沒有提到你正在使用的數據庫。讓我假設您正在使用支持排名功能的數據庫,因爲這簡化了解決方案。

解決這個問題的關鍵是觀察。你想給每個pid分配一個id來查看它是否唯一。我假設一個pid代表一個單獨的進程,當pid在前一個時間戳輸出中出現而不是時。現在

,這個想法是:

  1. 分配一個序列號,每一組輸出。第一次調用ps得到1,接下來的2,依此類推,基於日期。
  2. 根據日期爲每個PID指定一個序列號。首先出現1,然後2,依此類推。
  3. 對於按順序出現的pid,差異是一個常數。我們可以將這稱爲該組的id。

所以,這是在動作查詢:

select groupid, pid, min(time), max(time) 
from (select t.*, 
      (dense_rank() over (order by time) - 
       row_number() over (partition by pid order by time) 
      ) as groupid 
     from t 
    ) t 
group by groupid, pid 

這在大多數數據庫(SQL服務器,Oracle,DB2,Postgres的,Teradata的,等等)。它在MySQL中不起作用,因爲MySQL不支持窗口/分析功能。

相關問題