SQL:如果事件发生,将时间序列table转换为开始-结束时间table

SQL: transposing a time series table into a start-end time table if an event occur

我正在尝试使用 select 语句来创建视图,将带有日期时间的 table 转换为每行包含记录的 table,开始结束时间'record' 字段中按时间(按站点划分)的连续值不为 0。

这是初始 table 的示例。

以及转置后的样子。

有人能帮忙吗?

ROW_NUMBER() 最适合分区。接下来,您可以对分区表进行自连接,看看时间差是否大于五分钟。我认为最好的解决方案是根据时间戳差异的滚动总和进行分区,根据您的模式偏移 5 分钟。如果五分钟不是常规模式,那么可能有一种通用方法可以与零一起使用。

为方便视图创建而在下面编写为 CTE 的解决方案(尽管视图速度较慢)。

WITH partitioned as (
    SELECT datetime, station, recording, 
    ROW_NUMBER() OVER(PARTITION BY station
    ORDER BY datetime ASC) rn
    FROM table --Not sure what the tablename is
    WHERE recording != 0),
diffed as (
    SELECT a.datetime, a.station, 
    DATEDIFF(mi,ISNULL(b.datetime,a.datetime),a.datetime)-5) Difference
    --The ISNULL logic is for when a.datetime is the beginning of the block,
    --we want a 0
    FROM partitioned a
    LEFT JOIN partitioned b on a.rn = b.rn + 1 and a.station=b.station
    GROUP BY a.datetime,a.station),
cumulative as (
    SELECT a.datetime, a.station, SUM(b.difference) offset_grouping
    FROM diff a
    LEFT JOIN diff b on a.datetime >= b.datetime and a.station = b.station ),
ordered as (SELECT datetime,station, 
    ROW_NUMBER() OVER(PARTITION BY station,offset_grouping ORDER BY datetime asc) starter, 
    ROW_NUMBER() OVER(PARTITION BY station,offset_grouping ORDER BY datetime desc) ender
    FROM cumulative)
SELECT ROW_NUMBER() OVER(ORDER BY a.datetime) unique_id,a.station,a.datetime startdate, b.datetime enddate
FROM ordered a
JOIN ordered b on a.starter = b.ender and a.station=b.station and a.starter=1

这是我能想到的唯一解决方案,但同样,它的速度很慢,具体取决于您拥有的数据量。

您可以使用 conditional_change_event 分析函数来创建一个特殊的分组标识符,以便在一个简单的查询中将它们分开:

select row_number() over () unique_id, 
       station, 
       min(datetime) startdate, 
       max(datetime) enddate
from  (
  select t.*, CONDITIONAL_CHANGE_EVENT(decode(recording,0,0,1)) 
              over (partition by station order by datetime) chg
  from mytable t
) x
where recording > 0
group by station, chg
order by 1, 2

解码只是为了设置你的岛和间隙(其中间隙正在记录 <= 0 并且岛屿正在记录 > 0)。那么那上面的change事件就会生成一个新的标识符进行分组。另请注意,我正在对更改事件进行分组,即使它不是输出的一部分。