2017-02-13 7 views
1

У меня есть набор данных, показанный ниже. Из этого я хочу выбрать первую строку из каждой группы, где статус PersonIDs был изменен на другой статус, чем предыдущий.Как сгруппировать эти данные без использования функции LAG

Например, из этого набора данных мне нужны строки 1, 4, 7 и 11. Любая помощь по этому вопросу? Если я делаю GROUPBY, он просто объединяет все новые и все ожидающие в 2 группы. У меня только SQL Server 2008, поэтому функция задержки не будет работать.

PersonID Status WhenChanged 
101   New  27/01/2017 15:27 
101   New  27/01/2017 16:40 
101   New  27/01/2017 16:40 
101   Pending 27/01/2017 16:40 
101   Pending 27/01/2017 16:40 
101   Pending 27/01/2017 16:40 
101   New  31/01/2017 09:14 
101   New  31/01/2017 10:02 
101   New  31/01/2017 10:03 
101   New  31/01/2017 10:05 
101   Pending 03/02/2017 14:29 
101   Pending 03/02/2017 14:29 
+0

Действительно ли ваш «WhenChanged» имеет значение «VARCHAR» ...? – Siyual

+1

С вашей структурой это невозможно. Ваши значения datetime (которые выглядят подозрительно, как «VARCHAR») * не уникальны. Вам нечего сортировать. И без каких-либо приказов этих результатов нет гарантированного порядка ваших результатов. Таким образом, невозможно получить желаемые результаты. Вам нужен уникальный идентификатор для записей. – Siyual

ответ

4

Вы можете сделать это с разницей row_numbers(), а затем другой row_number():

select PersonID, Status, WhenChanged 
from (select t.*, 
      row_number() over (partition by personid, status, seqnum_p - seqnum_ps 
           order by whenchanged 
           ) as seqnum 
     from (select t.*, 
        row_number() over (partition by personid order by whenchanged) as seqnum_p, 
        row_number() over (partition by personid, status order by whenchanged) as seqnum_ps 
      from t 
      ) t 
    ) t 
where seqnum = 1; 

Чтобы понять, как это работает, я хотел бы предложить вам запустить подзапросы и посмотреть на результаты. Разница между этими номерами строк определяет группы.

Альтернативой является использование outer apply. Однако вышеизложенное, вероятно, имеет лучшую производительность.

+0

Большое спасибо Гордон, это прекрасно работает :-) – Tan