SQL 中的相干间隔?

Coherent intervals in SQL?

考虑一个简单的日记 table:

 Date   Mood
 ----   ----
 1      Good
 2      Good
 3      Good
 4      Bad
 5      Bad
 6      Good

我对情绪间隔感兴趣,因此我会得到这样的结果:

 Mood   BeginDate   EndDate
 ----   ---------   -------
 Good   1           3
 Bad    4           5 
 Good   6           6

在 SQL 中可以不使用迭代吗?

如果从每种心情的开始日期中减去一个序列号,当值相邻时,您将得到一个常数:

 Date   Mood    Seqnum
 1      Good       1
 2      Good       2
 3      Good       3
 4      Bad        1
 5      Bad        2
 6      Good       4

然后你可以使用聚合来做你想做的事。如果 date 真的是一个数字:

select mood, min(date), max(date)
from (select t.*,
             row_number() over (partition by mood order by date) as seqnum
      from t
     ) t
group by mood, (date - seqnum);

如果date真的是date:

select mood, min(date), max(date)
from (select t.*,
             row_number() over (partition by mood order by date) as seqnum
      from t
     ) t
group by mood, dateadd(day, - seqnum, date)

在 Gordon Linoff 的回答中回应这条评论:

If date is really a number:

如果不是怎么办?只要稍作调整,您还有前进的道路。

WITH d AS (
    SELECT * FROM (VALUES
        (cast('2021-04-22 00:00' as datetime2(0)), 'Good'),
        (cast('2021-04-22 00:05' as datetime2(0)), 'Good'),
        (cast('2021-04-22 00:07' as datetime2(0)), 'Good'),
        (cast('2021-04-22 00:10' as datetime2(0)), 'Bad'),
        (cast('2021-04-22 00:25' as datetime2(0)), 'Bad'),
        (cast('2021-04-22 01:43' as datetime2(0)), 'Good')
    ) AS x([date], mood)        
), t AS (
    SELECT *, 
        ROW_NUMBER() OVER (ORDER BY [date]) AS a,
        ROW_NUMBER() OVER (PARTITION BY mood ORDER BY [date]) AS seqnum
    FROM d
)
select mood, min(date), max(date)
from t
group by mood, a - seqnum
order by min(date)

分解一下,第一个 cte 只是您的数据,但现在 date 使用日期时间列而不是整数。请注意,连续行之间的间隔不是恒定的(它可以是,但我这样做是为了表明它 不需要 是)。从那里,我们使用 row_number() 函数计算两个值 - 一个枚举整个集合,另一个按情绪划分。其余的(在精神上)与戈登的回答相同。