CTE 递归加入 table

CTE Recursively join table

我有一个 table 个 ID,每次更新该 ID 时都会更新状态代码和时间戳,例如:

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

这行得通,但我必须对每个状态都这样做,并且大约有 12 个不同的状态代码。我已经阅读了几个进行草书连接的示例,并理解了这个概念,但实际上将它应用于我的查询时遇到了很多麻烦。本质上我想说的是递归位是 Status = Previous Status + 10, 但是如何实现这个很麻烦。

我不明白如何获取最近的状态并向其添加 10。

您可以使用条件聚合:

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

Gordon Linoff 的解决方案非常适合我,但后来我了解了 PIVOT 函数,经过反复试验,发现以下给了我想要的 table 结果:

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