2012-09-14 34 views
0

由於某種原因,我看到我的時間間隔使用此查詢的差距。在使用基本數據時,我已經完成了它的工作。但是,當加入我的表並指定WHERE子句時,我發現我的時間間隔存在差距。我還需要在我的時間間隔中包含S.SessionEndTime,以查找與ResponseTime和SessionEndTime之間的給定1分鐘時間間隔重疊的記錄計數。避免在日期時間間隔與CTE和開始和結束日期差距

這是我正在使用的查詢。通過使用派生表,每1分鐘的時間間隔內,我會根據COUNT得到一個MAX每小時的最大值。

+0

那麼,CTE看起來很熟悉。你能舉出一個輸入和輸出的例子,指出看起來有什麼問題嗎?你期望'GROUP BY'和'ORDER BY'子句做什麼。 – HABO

+0

您的各種轉換似乎設計用於確定日期/時間的「最佳時間」。把它放在一個明確命名的函數中會使代碼更容易解​​釋。我也避免了文本和文本之間的轉換,並且使用更類似的東西:'declare @Now as DateTime = GetDate();選擇@Now作爲'Now',將DateAdd(小時,DatePart(小時,@Now),Cast(演員(@Now as Date)作爲DateTime))設置爲'Top Of The Hour'。 – HABO

+0

添加了我得到的輸出以及我想要從中獲得的輸出。謝謝HABO! – user1644708

回答

0

好的,這裏沒有澄清一些計算兩者的TSQL: - 每小時活動的會話總數和 - 每小時活動的最大併發會話數。

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

相關問題