通过SQL确定“组”记录之间时间差的集合论方法

时间:2009-11-03 20:44:15

标签: sql sql-server

我在SqlServer中有一个日志文件,它存储应用程序启动的时间,应用程序就绪的时间(即已完成加载)以及退出的时间。每个都作为单独的条目出现。格式(和样本数据)如下:

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

有什么建议吗?

编辑:好消息是应用程序只能启动一次。但是,如果应用程序崩溃,日志会考虑(尽管我认为我可以寻找“退出”和“崩溃”作为最终条件)。

2 个答案:

答案 0 :(得分: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的解决方案一样,当同一用户多次使用该应用程序时,它无法处理这种情况。您需要第三个分组列(如“会话”或其他内容)来处理该场景。

答案 1 :(得分: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