2012-09-14 4 views
0

어떤 이유로이 쿼리를 사용하여 시간 간격에 차이가 있습니다. 기본 데이터를 사용할 때 작동하도록했습니다. 그러나 테이블을 조인하고 WHERE 절을 지정할 때마다 필자의 시간 간격에 차이가 있음을 알 수 있습니다. 또한 ResponseTime과 SessionEndTime 사이의 1 분 간격으로 겹치지 않는 레코드 수를 찾으려면 S.SessionEndTime을 일정 간격으로 통합해야합니다.CTE와 datetime 간격의 간격을 피하고 시작 및 끝 날짜 시간

다음은 내가 사용중인 쿼리입니다. 파생 테이블을 사용하면 1 분 간격의 COUNT에 따라 시간당 MAX가 계산됩니다.

+0

글쎄, CTE는 친숙 해 보인다. 무엇이 잘못되었다는 표시로 입력과 출력의 예를 보여줄 수 있습니까? 그리고'GROUP BY'와'ORDER BY' 조항이 기대하는 것. – HABO

+0

다양한 전환은 날짜/시간에서 "최고 시간"을 결정하도록 설계되었습니다. 이를 명확하게 명명 된 함수에 넣으면 코드를 훨씬 쉽게 해석 할 수 있습니다. 나는 또한 텍스트와의 변환을 피하고 다음과 같은 것을 사용한다.'declare @Now as DateTime = GetDate(); 'Now', DateAdd (시간, DatePart (시간, @Now), Cast (날짜로 @Now as Date))를 'Top Of The Hour'로 선택하십시오. – HABO

+0

내가 얻은 결과와 나가고 싶은 것을 추가했습니다. 감사합니다. HABO! – user1644708

답변

0

여기에 설명이 없으면 - 각 시간에 활성화 된 총 세션 수 및 - 각 시간에 활성화 된 최대 동시 세션 수입니다.

EDIT : 업데이트 된 질문에서 샘플 데이터 해주기 동시 세션을 표시하고 마지막 질의의 출력이 상기 세션 ID를 포함하고, 사용되었으며, 종래의 최적화 버그 크게 성능이 향상 수정되었습니다 .

NB :이 쿼리는 SessionId 값이 행마다 다를 때 가장 잘 작동합니다. 모든 행에 1 값을 사용하면 실망스러운 결과가 발생합니다. 따라서 SessionId 열의 IDENTITY 속성 다음

-- Parameters. 
declare @Start as DateTime = '20120901 00:00:00' 
declare @End as DateTime = '20120901 12:00:00' 
declare @Interval as Time = '01:00:00.00' -- One hour. 
select @Start as [Start], @End as [End], @Interval as [Interval] 

-- Sample data. 
declare @Sessions as Table (SessionId Int Identity, SessionStart DateTime, SessionEnd DateTime) 
insert into @Sessions (SessionStart, SessionEnd) values 
    ('20120901 00:00:00', '20120901 05:59:59'), -- Several hours in a single session. 
    ('20120901 01:01:00', '20120901 01:01:30'), -- An assortment of overlapping ... 
    ('20120901 01:02:00', '20120901 01:03:30'), -- ... sessions during a single hour. 
    ('20120901 00:00:05.077', '20120901 00:04:02.280'), 
    ('20120901 00:00:14.687', '20120901 00:06:05.947'), 
    ('20120901 00:00:17.857', '20120901 00:07:34.757'), 
    ('20120901 00:00:25.843', '20120901 00:07:38.720'), 
    ('20120901 00:00:29.427', '20120901 00:01:58.180'), 
    ('20120901 00:00:31.853', '20120901 00:05:10.733'), 
    ('20120901 00:00:40.693', '20120901 00:00:44.237'), 
    ('20120901 00:00:58.773', '20120901 00:06:14.667'), 
    ('20120901 00:00:59.457', '20120901 00:01:01.310'), 
    ('20120901 00:01:16.390', '20120901 00:11:18.383') 
select * from @Sessions 

-- Summary of sessions active at any time during each hour. 
; with SampleWindows as ( 
    select @Start as WindowStart, @Start + @Interval as WindowEnd 
    union all 
    select SW.WindowStart + @Interval, SW.WindowEnd + @Interval 
    from SampleWindows as SW 
    where SW.WindowEnd < @End 
) 
    select SW.WindowStart, Count(S.SessionStart) as [Sessions] 
    from SampleWindows as SW left outer join 
     @Sessions as S on SW.WindowStart <= S.SessionEnd and S.SessionStart < SW.WindowEnd 
    group by SW.WindowStart 

-- Summary of maximum concurrent sessions active during each hour. 
; with SampleWindows as ( 
    select 1 as SampleWindowId, @Start as WindowStart, @Start + @Interval as WindowEnd 
    union all 
    select SW.SampleWindowId + 1, SW.WindowStart + @Interval, SW.WindowEnd + @Interval 
    from SampleWindows as SW 
    where SW.WindowEnd < @End 
), 
    ActiveSessionsDuringWindow as ( 
    select SW.SampleWindowId, SW.WindowStart, SW.WindowEnd, S.SessionId, S.SessionStart, S.SessionEnd, 
    -- A "pane" is the more restrictive of the window and the session start/end times. 
    case when SW.WindowStart <= S.SessionStart then S.SessionStart else SW.WindowStart end as PaneStart, 
    case when SW.WindowEnd >= S.SessionEnd then S.SessionEnd else SW.WindowEnd end as PaneEnd 
    from SampleWindows as SW left outer join 
     @Sessions as S on SW.WindowStart <= S.SessionEnd and S.SessionStart < SW.WindowEnd 
), 
    ConcurrentSearch as ( 
    select SampleWindowId, WindowStart, WindowEnd, SessionId, SessionStart, SessionEnd, PaneStart, PaneEnd, 
    Cast('|' + Right(Replicate('0', 3) + Cast(SessionId as VarChar(4)), 4) + '|' as VarChar(1024)) as SessionIds, 
    Cast(case when SessionId is NULL then 0 else 1 end as Int) as Sessions 
    from ActiveSessionsDuringWindow 
    union all 
    select CS.SampleWindowId, CS.WindowStart, CS.WindowEnd, ASDW.SessionId, CS.SessionStart, CS.SessionEnd, 
    case when CS.PaneStart <= ASDW.PaneStart then ASDW.PaneStart else CS.PaneStart end as PaneStart, 
    case when CS.PaneEnd >= ASDW.PaneEnd then ASDW.PaneEnd else CS.PaneEnd end as PaneEnd, 
    Cast(CS.SessionIds + Right(Replicate('0', 3) + Cast(ASDW.SessionId as VarChar(4)), 4) + '|' as VarChar(1024)), 
    CS.Sessions + 1 
    from ConcurrentSearch as CS inner join 
     ActiveSessionsDuringWindow as ASDW on ASDW.SampleWindowId = CS.SampleWindowId and 
     -- We haven't visited this session along this path. 
     CS.SessionId < ASDW.SessionId and -- EDIT: Reduce the size of the search tree. 
     CharIndex('|' + Right(Replicate('0', 3) + Cast(ASDW.SessionId as VarChar(4)), 4) + '|', CS.SessionIds) = 0 and 
     -- The session's pane overlaps the concurrent search pane. 
     CS.PaneStart <= ASDW.PaneEnd and ASDW.PaneStart <= CS.PaneEnd 
) 
    select WindowStart, Max(Sessions) as Sessions, 
    (select top 1 SessionIds from ConcurrentSearch where Sessions = Max(CS.Sessions)) as SessionIds 
    from ConcurrentSearch as CS 
    group by WindowStart 

@Sessions 테이블에서 행 ID 값을 사용하지 않습니다 마지막 쿼리의 변형이다. 대신 Row_Number()을 사용하여 쿼리 기간 동안 적절한 값을 할당합니다. 또한 SessionId 값이 주어진 시간 내에 9,999 세션을 초과하지 않는다는 가정하에 네 자리를 초과하지 않는다는 가정을 변경합니다.

-- Summary of maximum concurrent sessions active during each hour. 
; with SampleWindows as ( 
    select 1 as SampleWindowId, @Start as WindowStart, @Start + @Interval as WindowEnd 
    union all 
    select SW.SampleWindowId + 1, SW.WindowStart + @Interval, SW.WindowEnd + @Interval 
    from SampleWindows as SW 
    where SW.WindowEnd < @End 
), 
    ActiveSessionsDuringWindow as ( 
    select SW.SampleWindowId, SW.WindowStart, SW.WindowEnd, S.SessionStart, S.SessionEnd, 
    -- A "pane" is the more restrictive of the window and the session start/end times. 
    case when SW.WindowStart <= S.SessionStart then S.SessionStart else SW.WindowStart end as PaneStart, 
    case when SW.WindowEnd >= S.SessionEnd then S.SessionEnd else SW.WindowEnd end as PaneEnd, 
    Row_Number() over (partition by SW.SampleWindowId order by S.SessionStart) as SampleId 
    from SampleWindows as SW left outer join 
     @Sessions as S on SW.WindowStart <= S.SessionEnd and S.SessionStart < SW.WindowEnd 
), 
    ConcurrentSearch as ( 
    select SampleWindowId, WindowStart, WindowEnd, SampleId, SessionStart, SessionEnd, PaneStart, PaneEnd, 
    Cast('|' + Right(Replicate('0', 3) + Cast(SampleId as VarChar(4)), 4) + '|' as VarChar(1024)) as SampleIds, 
    Cast(case when SampleId is NULL then 0 else 1 end as Int) as Sessions 
    from ActiveSessionsDuringWindow 
    union all 
    select CS.SampleWindowId, CS.WindowStart, CS.WindowEnd, ASDW.SampleId, CS.SessionStart, CS.SessionEnd, 
    case when CS.PaneStart <= ASDW.PaneStart then ASDW.PaneStart else CS.PaneStart end as PaneStart, 
    case when CS.PaneEnd >= ASDW.PaneEnd then ASDW.PaneEnd else CS.PaneEnd end as PaneEnd, 
    Cast(CS.SampleIds + Right(Replicate('0', 3) + Cast(ASDW.SampleId as VarChar(4)), 4) + '|' as VarChar(1024)), 
    CS.Sessions + 1 
    from ConcurrentSearch as CS inner join 
     ActiveSessionsDuringWindow as ASDW on ASDW.SampleWindowId = CS.SampleWindowId and 
     -- We haven't visited this session along this path. 
     CS.SampleId < ASDW.SampleId and -- EDIT: Reduce the size of the search tree. 
     CharIndex('|' + Right(Replicate('0', 3) + Cast(ASDW.SampleId as VarChar(4)), 4) + '|', CS.SampleIds) = 0 and 
     -- The session's pane overlaps the concurrent search pane. 
     CS.PaneStart <= ASDW.PaneEnd and ASDW.PaneStart <= CS.PaneEnd 
) 
    select WindowStart, Max(Sessions) as Sessions 
    from ConcurrentSearch as CS 
    group by WindowStart 

기존 테이블에 대해 실행하기 쉽도록 수정해야합니다. SessionStart의 오름차순 단일 인덱스는 오름차순의 SessionEnd으로 성능을 향상시킵니다.

+0

데이터의 데이터가 실제로 보이는 모양을 포함하도록 게시물을 업데이트했습니다. – user1644708

+0

실제 데이터로이 쿼리를 테스트하고 있습니다. 주어진 시간 동안 100에 가까워지는 행을 처리하는 경우 실행이 완료되지 않는 것처럼 보입니다. 마치 무한 루프에있는 것과 같습니다. 어떤 아이디어? – user1644708

+0

어제 나는 CS_SessionId HABO