2010-04-29 78 views
1

我有一個表格(ROOMUSAGE),其中包含按人員和ROOMKEY分組的人員進出房間的時間。它看起來像這樣:在分組表格中應用遞歸CTE(SQL Server 2005)

PERSONKEY | ROOMKEY | CHECKIN   | CHECKOUT   | ROW 
---------------------------------------------------------------- 
1   | 8  | 13-4-2010 10:00 | 13-4-2010 11:00 | 1 
1   | 8  | 13-4-2010 08:00 | 13-4-2010 09:00 | 2 

1   | 1  | 13-4-2010 15:00 | 13-4-2010 16:00 | 1 
1   | 1  | 13-4-2010 14:00 | 13-4-2010 15:00 | 2 
1   | 1  | 13-4-2010 13:00 | 13-4-2010 14:00 | 3 

13  | 2  | 13-4-2010 15:00 | 13-4-2010 16:00 | 1 
13  | 2  | 13-4-2010 15:00 | 13-4-2010 16:00 | 2 

我想爲每個PERSONKEY,ROOMKEY分組只選擇連續的行。所以期望的結果表是:

PERSONKEY | ROOMKEY | CHECKIN   | CHECKOUT   | ROW 
---------------------------------------------------------------- 
1   | 8  | 13-4-2010 10:00 | 13-4-2010 11:00 | 1 

1   | 1  | 13-4-2010 15:00 | 13-4-2010 16:00 | 1 
1   | 1  | 13-4-2010 14:00 | 13-4-2010 15:00 | 2 
1   | 1  | 13-4-2010 13:00 | 13-4-2010 14:00 | 3 

13  | 2  | 13-4-2010 15:00 | 13-4-2010 16:00 | 1 

我想避免使用遊標,所以我想我會使用遞歸CTE。以下是我想出了:

;with CTE (PERSONKEY, ROOMKEY, CHECKIN, CHECKOUT, ROW) 
as (select RU.PERSONKEY, 
      RU.ROOMKEY, 
      RU.CHECKIN, 
      RU.CHECKOUT, 
      RU.ROW 
    from ROOMUSAGE RU 
    where RU.ROW = 1 

    union all 

    select RU.PERSONKEY, 
      RU.ROOMKEY, 
      RU.CHECKIN, 
      RU.CHECKOUT, 
      RU.ROW 
    from ROOMUSAGE RU inner join CTE on RU.ROW = CTE.ROW + 1 
    where CTE.CHECKIN = RU.CHECKOUT 
     and CTE.PERSONKEY = RU.PERSONKEY 
     and CTE.ROOMKEY = RU.ROOMKEY) 

這工作確定了非常小的數據集(在100條記錄),但它在大型數據集不可用。

我在想,我應該以某種方式將cte recursevely應用到我的ROOMUSAGE表上的每個人,ROOMKEY組中,但我不知道該怎麼做。

任何幫助將不勝感激,

乾杯!

+0

有你看着的查詢計劃這一點,我敢打賭RU的內連接到CTE是做表掃描您要加入的方式。 – BlackICE 2010-04-29 13:43:30

回答

0

有些事情要嘗試

  • 而是與加入每行和你的where子句中的過濾結果,你可以嘗試,如果減少直接在連接速度事情的記錄是多少?
  • 在PersonKey,RoomKey,CheckOut & Row上添加覆蓋索引,查看它是否可以提高性能。

SQL語句

;with CTE (PERSONKEY, ROOMKEY, CHECKIN, CHECKOUT, ROW) 
as (select RU.PERSONKEY, 
      RU.ROOMKEY, 
      RU.CHECKIN, 
      RU.CHECKOUT, 
      RU.ROW 
    from ROOMUSAGE RU 
    where RU.ROW = 1 

    union all 

    select RU.PERSONKEY, 
      RU.ROOMKEY, 
      RU.CHECKIN, 
      RU.CHECKOUT, 
      RU.ROW 
    from ROOMUSAGE RU 
     inner join CTE on CTE.ROW + 1 = RU.ROW 
          and CTE.CHECKIN = RU.CHECKOUT 
          and CTE.PERSONKEY = RU.PERSONKEY 
          and CTE.ROOMKEY = RU.ROOMKEY 
) 
+0

對不起,我應該澄清ROOMUSAGE是在CTE之前創建的另一個非遞歸cte。基礎表全部編入索引。 我已經試過你的建議,並注意到,當我從CTE做select *時,我得到所有行= 1行,然後它卡住處理其餘的行。當我從連接中刪除PERSONKEY和ROOMKEY條件時,我幾乎獲得了所有記錄,但又一次卡住了...... – 2010-04-29 14:57:38

+0

在這種情況下,創建臨時#ROOMUSAGE表可能會更快,添加索引並使用臨時表在CTE中。 – 2010-04-29 15:01:16

+0

感謝列文,使用臨時表大大提高了性能。 – 2010-04-29 15:31:00