2009-11-03 2 views
1

응용 프로그램이 시작된 시간, 응용 프로그램 준비가 완료된 시간 (즉,로드가 완료된 시간)을 저장하는 로그 파일이 SqlServer에 있습니다. 그것이 종료 된 시간. 이들 각각은 별도의 항목으로 발생합니다. 다음과 같이 형식 (샘플 데이터)입니다 :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 

어떤 제안?

편집 : 좋은 소식은 응용 프로그램을 한 번만 시작할 수 있다는 것입니다. 하지만 로그는 이 아니며은 응용 프로그램이 손상된 경우를 고려합니다 (최종 조건으로 "종료"및 "손상됨"을 찾을 수는 있겠지만).

답변

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

우물 ... 끔찍한 코멘트 (농담 만하는 것)에 너무 감사드립니다! 당신은 매우 환영합니다! –

3

특히 테이블이 커지면 동일한 테이블에 여러 번 가입하지 않는 것이 좋습니다. 이는 일종의 2 단계 접근 방법입니다. 첫 번째 패스는 적절한 장소에 시간을 정렬하고 두 번째 패스는 사용자와 응용 프로그램에서 그들을 폴드 :

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_ 시간을 제공합니다. 나는 주어진 시간 동안 _each_ start/exit를 줄 수있는 무엇인가를 원했다. 그래도 계속 노력하겠습니다. –

관련 문제