Применение рекурсивного CTE к строкам сгруппированных таблиц (SQL Server 2005) - PullRequest
1 голос
/ 29 апреля 2010

У меня есть таблица (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 записей), но его нельзя использовать для больших наборов данных.

Я думаю, что я должен каким-то образом применять cte recurnvely для каждой группы PERSONKEY, ROOMKEY на моей таблице ROOMUSAGE, но я не уверен, как это сделать.

Любая помощь будет высоко ценится,

ура!

1 Ответ

0 голосов
/ 29 апреля 2010

Некоторые вещи попробовать

  • Вместо объединения с каждой строкой и фильтрации результатов в предложении 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
)
...