;WITH CTE
AS ( SELECT rownum = ROW_NUMBER() OVER ( ORDER BY sd.slogid desc) ,
sd.slogid ,
sd.sid ,
sd.statusid
FROM statusdetails sd
)
SELECT TOP ( 1 )
cte.slogid,
CTE.statusid,
cte.sid ,
nex.stausid NextValue
FROM CTE
LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1
LEFT JOIN CTE nex ON nex.rownum = CTE.rownum + 1
WHERE CTE.statusid <> nex.statusid
我的n
数量为sid
,并希望获得每个群组top 1
。
示例数据:
Slogid Sid Statusid
186877 98929 105
186826 98929 105
186821 98929 104
我希望得到slogid
- 186826,当状态发生变化时,我想从每个Sid
组获取状态。
答案 0 :(得分:2)
;WITH CTE AS
( SELECT ROW_NUMBER() OVER (PARTITION BY sid ORDER BY sd.slogid desc) RN,
sd.slogid ,
sd.sid ,
sd.statusid
FROM statusdetails sd
)
SELECT TOP ( 1 )
cte.slogid,
CTE.statusid,
cte.sid ,
nex.stausid NextValue
FROM CTE
LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1
LEFT JOIN CTE nex ON nex.rownum = CTE.rownum + 1
WHERE CTE.statusid <> nex.statusid
AND RN = 1;
答案 1 :(得分:2)
您似乎需要按sid
对row_number函数进行分区,以确保状态更改链接到同一sid
:
rownum = ROW_NUMBER() OVER (PARTITION BY `sid` ORDER BY sd.slogid desc) ,
假设这就是你想要的,那么你在这里错过了一个JOIN条件:
FROM CTE
LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1
LEFT JOIN CTE nex ON nex.rownum = CTE.rownum + 1
您还需要加入sid
,否则您将获得交叉加入,因此您的加入应该是:
FROM CTE
LEFT JOIN CTE prev ON prev.sid = CTE.sid AND prev.rownum = CTE.rownum - 1
LEFT JOIN CTE nex ON nex.sid = CTE.sid AND nex.rownum = CTE.rownum + 1
我不知道为什么你加入到之前,因为你从来没有在选择中实际使用它。我个人更倾向于使用APPLY来获取以前的状态:
SELECT sd.slogid ,
sd.sid,
sd.statusid,
NextValue = n.statusid
FROM statusdetails AS sd
CROSS APPLY
( SELECT TOP 1 n.statusid
FROM statusdetails AS n
WHERE n.sid = sd.sid
AND n.slogid > sd.slogid
ORDER BY n.slogid
) n
WHERE sd.statusid != n.statusid;
最后,我不确定你是否想要每个sid的前1个记录,或者只是最顶层的记录。在您的查询中,您使用TOP
而没有order by子句,这不是确定性的,所以不应该这样做。如果你想要每个sid的前1名,你需要使用ROW_NUMBER
来获得这个:
WITH CTE AS
( SELECT sd.slogid ,
sd.sid,
sd.statusid,
NextValue = n.statusid,
RowNum = ROW_NUMBER() OVER(PARTITION BY sd.sid ORDER BY sd.slogid DESC)
FROM statusdetails AS sd
CROSS APPLY
( SELECT TOP 1 n.statusid
FROM statusdetails AS n
WHERE n.sid = sd.sid
AND n.slogid > sd.slogid
ORDER BY n.slogid
) n
WHERE sd.statusid != n.statusid
)
SELECT slogid, sid, statusid, NextValue
FROM CTE
WHERE RowNum = 1;
<强> Example on SQL Fiddle 强>
为了完整起见,这是您的查询(使用ROW_NUMBER获取下一个状态)并进行了更正:
WITH CTE AS
( SELECT rownum = ROW_NUMBER() OVER (PARTITION BY sd.sid ORDER BY sd.slogid desc) ,
sd.slogid ,
sd.sid ,
sd.statusid
FROM statusdetails sd
), CTE2 AS
( SELECT cte.slogid,
CTE.statusid,
cte.sid ,
NextValue = nex.statusid,
RowNum = ROW_NUMBER() OVER(PARTITION BY cte.sid ORDER BY cte.slogid DESC)
FROM CTE
LEFT JOIN CTE nex
ON nex.sid = CTE.sid
AND nex.rownum = CTE.rownum + 1
WHERE CTE.statusid <> nex.statusid
)
SELECT slogid, statusid, sid, NextValue
FROM CTE2
WHERE RowNum = 1;
<强> Example on SQL Fiddle 强>
答案 2 :(得分:0)
试试这个
;WITH CTE AS
(SELECT
rownum = ROW_NUMBER() OVER ( ORDER BY sd.slogid desc) ,
grouprownum = ROW_NUMBER() OVER ( PARTITION BY sd.[sid] ORDER BY sd.slogid desc)
sd.slogid ,
sd.sid ,
sd.statusid
FROM
statusdetails sd
)
SELECT
cte.slogid,
CTE.statusid,
cte.sid ,
nex.stausid NextValue
FROM CTE
LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1
LEFT JOIN CTE nex ON nex.rownum = CTE.rownum + 1
WHERE CTE.statusid <> nex.statusid
AND CTE.grouprownum=1