您如何从 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
在我的 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