2009-11-03 27 views
1

我在SqlServer中有一個日誌文件,用於存儲應用程序啓動的時間,應用程序準備就緒(即完成加載)的時間以及它退出的時間。這些都是作爲單獨的條目出現的。格式(和樣本數據)如下:Set-theory通過SQL確定「組」記錄之間的時間差的方式

Date/Time     User Type Application Message 
2009-11-03 12:26:12.403 uname1 Info app1   Started  
2009-11-03 12:26:22.403 uname1 Info app1   Loaded 
2009-11-03 12:27:15.403 uname2 Info app1   Started  
2009-11-03 12:27:16.401 uname1 Info app1   Exited 
2009-11-03 12:27:18.403 uname2 Info app1   Loaded 
2009-11-03 12:29:12.403 uname2 Info app1   Exited 

我想找到答案,每個應用程序和每個用戶,花費的時間爲應用量去就緒狀態和量應用程序運行的時間。如果每個日期/時間都在同一條記錄中,這將是小菜一碟,並且將每條記錄作爲光標加載並篩選數據也很容易(雖然很乏味),但我認爲必須存在某種方式以集合論的方式「正確地」做到這一點。

因此,要重申的是,下面的輸出(來自從上述樣本數據)將被預期(數量單位爲秒,四捨五入):

User Application Ready Uptime 
uname1 app1   10  64 
uname2 app1   3  117 

任何建議?

編輯:好消息是應用程序只能啓動一次。但是,日誌確實而不是考慮到應用程序崩潰(儘管我想我可以查找「exited」和「crash」作爲最終條件)。

回答

2

如何

Select S.user, S.Application, 
     S.DateTime Started, L.DateTime Loaded, X.DateTime Exited, 
     L.DateTime - S.DateTime LoadTime, 
     X.DateTime - L.DateTime RunTime 
    From LogFile S 
     Full Join LogFile L 
      On S.Message = 'Started' 
      And L.Message = 'Loaded' 
      And L.User = S.user 
      And L.Application = S.Application 
      And L.DateTime = (Select Min(DateTime) 
           From LogFile 
           Where Message = 'Loaded' 
           And application = S.Application 
           And user = S.user 
           And DateTime > S.DateTime) 
     Full Join LogFile X 
      On L.Message = 'Loaded' 
      And X.Message = 'Exited' 
      And X.User = L.user 
      And X.Application = L.Application 
      And X.DateTime = (Select Min(DateTime) 
           From LogFile 
           Where Message = 'Exited' 
            And application = L.Application 
            And user = L.user 
            And DateTime > L.DateTime) 

然後將集合函數這個你想要的東西:

Select user, Application, 
    Sum(LoadTime) TotLoadTime, 
    Sum(RunTime) TotalRunTime 
From 
     (Select S.user, S.Application, 
     S.DateTime Started, L.DateTime Loaded, X.DateTime Exited, 
     L.DateTime - S.DateTime LoadTime, 
     X.DateTime - L.DateTime RunTime 
     From LogFile S 
      Full Join LogFile L 
      On S.Message = 'Started' 
       And X.Message = 'Loaded' 
       And L.User = S.user 
       And L.Application = S.Application 
       And L.DateTime = 
         (Select Min(DateTime) 
         From LogFile 
         Where Message = 'Loaded' 
          And application = S.Application 
          And user = S.user 
          And DateTime > S.DateTime) 
     Full Join LogFile X 
      On L.Message = 'Loaded' 
       And X.Message = 'Exited' 
       And X.User = L.user 
       And X.Application = L.Application 
       And X.DateTime = 
         (Select Min(DateTime) 
         From LogFile 
         Where Message = 'Exited' 
          And application = L.Application 
          And user = L.user 
          And DateTime > L.DateTime)) Z 
Group By user, Application 
+0

雖然這是可怕的,但它確實有效。它只需要2秒的服務器時間來抓住它。謝謝。 –

+0

非常感謝你。我試圖設計出許多方法來解決這個問題,並且正要拋出我的手並編寫一個程序來做到這一點。這更容易和更快。 –

+0

wellll ...非常感謝這個可怕的評論(只是在開玩笑!)你非常歡迎! –

3

我寧願多次不加入同一張桌子,特別是如果桌子變大。這是一種雙通道方法。第一遍次排序到正確的地方,和第二次摺疊起來的用戶和應用程序:

SELECT 
    User, 
    Application, 
    MAX(StartTime) StartTime, 
    MAX(ReadyTime) ReadyTime, 
    MAX(ExitTime) ExitTime, 
FROM (
    SELECT 
    User, 
    Application, 
    CASE (
     WHEN Message = 'Started' THEN Date/Time 
     ELSE NULL 
    ) StartTime, 
    CASE (
     WHEN Message = 'Loaded' THEN Date/Time 
     ELSE NULL 
    ) ReadyTime, 
    CASE (
     WHEN Message = 'Exited' THEN Date/Time 
     ELSE NULL 
    ) ExitTime 
    FROM Log 
) Log 
GROUP BY 
    User, 
    Application 

從那裏是微不足道的計算所有你想在這些不同的時間。

這不是很「集合論」的樣子,但是分組和聚合永遠不會。像Eric的解決方案一樣,當同一用戶多次使用該應用程序時,它無法處理這種情況。你需要第三個分組列(如「會話」或其他)來處理這種情況。

+0

很不幸,這不僅賦予了_last_時間用戶啓動和退出應用程序。我希望有一些能夠在特定時間內啓動/退出的東西。不過,我會繼續努力。 –