CTE Рекурсивная таблица соединений - PullRequest
1 голос
/ 08 января 2020

У меня есть таблица идентификаторов, которая обновляется с кодом состояния и отметкой времени каждый раз, когда происходит обновление для этого идентификатора, например:

ID       STATUS     TIMESTAMP
------------------------------------
12345    10         2020-08-01 11:00:01
12345    20         2020-08-01 11:01:24
12345    30         2020-08-01 11:07:42

Я хочу, чтобы все изменения состояния и время в одной строке, поэтому я получаю:

ID       STATUS     TIMESTAMP           STATUS     TIMESTAMP           STATUS     TIMESTAMP
-----------------------------------------------------------------------------------------------------
12345    10         2020-08-01 11:00:01 20         2020-08-01 11:01:24 30         2020-08-01 11:07:42

Я могу сделать это, выполнив объединение для каждого статуса, поэтому мой запрос выглядит следующим образом:

with T1 as
(SELECT distinct
id as 'ID',
Status as 'STATUS',
Timestamp as 'Time10'
from StatusHistory S
where TimeStamp > '2020-01-07 11:00'
and Timestamp < '2020-01-07 11:10'
and Status = '10'),

T2 as
(SELECT distinct
id as 'ID',
Status as 'STATUS',
Timestamp as 'Time20'
from StatusHistory S
where TimeStamp > '2020-01-07 11:00'
and Timestamp < '2020-01-07 11:10'
and Status = '20')

Select * from T1
join T2 on T1.ID = T2.ID

This работает, но тогда я должен сделать это для каждого статуса, и есть около 12 различных кодов состояния. Я прочитал несколько примеров выполнения скоростного объединения и понял концепцию, но у меня возникли большие проблемы с ее применением к моему запросу. По сути, я хочу сказать, что для рекурсивного бита это Status = Previous Status + 10, , но как это реализовать, проблематично.

Я не понимаю, как получить самый последний статус и добавьте к нему 10.

Ответы [ 2 ]

0 голосов
/ 09 января 2020

Решение Гордона Линоффа отлично сработало для меня, но с тех пор я узнал о функции PIVOT, и после некоторых проб и ошибок обнаружил, что следующее дало мне таблицу результатов, за которой я был:

SELECT * FROM
(
    SELECT 
       id,
       status, 
       timestamp 
    FROM StatusHistory
       where TimeStamp > '2020-01-07 11:00'
       and Timestamp < '2020-01-07 11:10'
) dat
PIVOT
(
       MAX(Timestamp) FOR Status IN ([10], [20], [30], [40], [50], [60], [70], [80], [90], [100], [170]) 
) pvt
order by 10

Это дало мне результаты как:

ID      10                    20                    30
12345   2020-01-08 11:00:01   2020-01-08 11:01:24   2020-01-08 11:07:42
0 голосов
/ 08 января 2020

Вы можете использовать условное агрегирование:

select id,
       max(case when seqnum = 1 then status end) as status_1,
       max(case when seqnum = 1 then timestamp end) as timestamp_1,
       max(case when seqnum = 2 then status end) as status_2,
       max(case when seqnum = 2 then timestamp end) as timestamp_2,
       max(case when seqnum = 3 then status end) as status_3,
       max(case when seqnum = 3 then timestamp end) as timestamp_3
from (select sh.*,
             row_number() over (partition by id order by timestamp) as seqnum
      from StatusHistory sh
      where TimeStamp > '2020-01-07 11:00' and
            Timestamp < '2020-01-07 11:10'
     ) sh
group by id
...