Sql server 2005 对分组表行应用递归CTE(SQL server 2005)

Sql server 2005 对分组表行应用递归CTE(SQL server 2005),sql-server-2005,recursive-query,Sql Server 2005,Recursive Query,我有一个表(ROOMUSAGE),其中包含人们按PERSONKEY和ROOMKEY分组的进出房间的时间。看起来是这样的: PERSONKEY | ROOMKEY | CHECKIN | CHECKOUT | ROW ---------------------------------------------------------------- 1 | 8 | 13-4-2010 10:00 | 13-4-2010 11:00

我有一个表(ROOMUSAGE),其中包含人们按PERSONKEY和ROOMKEY分组的进出房间的时间。看起来是这样的:

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条记录)是可行的,但对于大型数据集是不可用的

我想我应该在我的ROOMUSAGE表中的每个PERSONKEY、ROOMKEY分组上递归地应用cte,但我不知道该怎么做

任何帮助都将不胜感激

干杯

有些事情需要尝试

  • 与其使用每一行加入并在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
)

你看过这个查询计划了吗,我敢打赌RU到CTE的内部连接是以你连接它的方式进行表扫描的。对不起,我应该澄清ROOMUSAGE是另一个非递归CTE,它是在CTE之前创建的。基础表都已编制索引。我尝试了你的建议,并注意到当我从CTE中选择*时,我得到了所有的行=1行,然后它在处理其余的行时被卡住了。当我从连接中删除PERSONKEY和ROOMKEY条件时,我几乎收回了所有记录,但它再次被卡住……在这种情况下,创建临时ROOMUSAGE表、添加索引并在CTE中使用临时表可能会更快。感谢Lieven,使用临时表大大提高了性能。