您如何从 LEAD 或 LAG 获得差距的大小?

How do you get the size of the gap from LEAD or LAG?

在我的 table 中,我有按主题分组的消息。使用 LEAD,我可以在线程中获取下一条消息...

[ThreadNextMessageId] = LEAD(gm.GroupMessageId, 1) OVER(PARTITION BY gm.ThreadId ORDER BY gm.GroupMessageId)

但是,当按GroupMessageId 排序时,如何知道线程中当前行和下一行之间有多少行? table 可能包含介于两者之间的其他线程的行,我也想计算这些行。

我找到了一种似乎可以做到这一点的方法,方法是将我的查询作为 CTE 括起来,然后使用 LEAD 生成的 ID 来计算当前 GroupMessageId 和 ThreadNextMessageId 之间的行数,但似乎应该有一个更有效的方法。

WITH cte AS (
    SELECT
        gm.GroupMessageId
        ,gm.ThreadId
        ,[ThreadNextMessageId] = LEAD(gm.GroupMessageId) OVER(PARTITION BY gm.ThreadId ORDER BY gm.GroupMessageId)
        ,[ThreadPrevMessageId] = LAG(gm.GroupMessageId) OVER(PARTITION BY gm.ThreadId ORDER BY gm.GroupMessageId)
    FROM dbo.GroupMessage gm
)
SELECT 
    cte.GroupMessageId
    ,cte.ThreadId
    ,cte.ThreadNextMessageId
    ,cte.ThreadPrevMessageId
    ,[ThreadNextOffset] = (SELECT COUNT(*) FROM cte c1 WHERE c1.GroupMessageId >= cte.GroupMessageId AND c1.GroupMessageId < cte.ThreadNextMessageId)
    ,[ThreadPrevOffset] = (SELECT COUNT(*) FROM cte c1 WHERE c1.GroupMessageId >= cte.ThreadPrevMessageId AND c1.GroupMessageId < cte.GroupMessageId)
FROM cte
ORDER BY cte.GroupMessageId

是否有另一种不需要 CTE 的方法来计算当前行与 LEAD 或 LAG 生成的行之间的行 - 也许使用其他一些 SQL window 函数?

我建议枚举所有行并使用算术:

WITH gm AS (
      SELECT gm.*,
             ROW_NUMBER() OVER (ORDER BY GroupMessageId) as seqnum
      FROM dbo.GroupMessage gm
     )
SELECT gm.*,
       (LEAD(seqnum) OVER (PARTITION BY gm.ThreadID ORDER BY gm.GroupMessageId) - seqnum - 1) as messages_in_between
FROM gm;
ORDER BY gm.GroupMessageId