在同一列中合并Dense_Rank()和Lag()

时间:2019-07-08 06:53:04

标签: sql sql-server dense-rank

我正在基于User IDTopic IDItem IDStatus生成尝试编号。

不幸的是,函数dense_rank()并没有完全实现我想要的功能;要获得全部要求,我想执行以下操作:

(1)使用dense_rank()创建一个视图,以添加尝试编号,其中status = started。这将忽略其他状态,为NULL

(2)使用NULL函数使用先前的“尝试号”值更新LAG()值。

我设法完成了步骤(1),但是,我努力寻找一种干净的方法来进行步骤(2)。

这是我的代码:

CREATE VIEW [StartedRank] AS
SELECT createdAt, USER_ID, Topic_ID, item_id, [status],
    CASE
        WHEN [status] = 'started' then 
        DENSE_RANK() OVER (PARTITION BY USER_ID, Topic_ID, item_id, [status] order by createdAt) 
        ELSE NULL
    END As AttemptNo
FROM [CurioTest].[dbo].[userprogressesv5]
WHERE type = 'practice' and user_id = '255251'
ORDER by createdAt

这将生成此表:

enter image description here

然后我尝试使用此代码更新表:

UPDATE StartedRank
SET AttemptNo = LAG(AttemptNo, 1) OVER (PARTITION BY user_ID, topic_ID, item_id ORDER BY createdAt)
WHERE AttemptNo is null

但是SQL不喜欢更新表,因为它包含一个派生字段。

要测试我的LAG()是否确实有效,我使用以下代码对其进行了测试:

SELECT *,
LAG(AttemptNo, 1) over (PARTITION BY user_ID, topic_ID, item_id ORDER BY createdAt) prevAttemptNo
FROM StartedRank

工作正常,结果截图如下:

enter image description here

任何见解都会受到赞赏。

1 个答案:

答案 0 :(得分:1)

像下面一样使用cte

with cte as
(
SELECT *,
LAG(AttemptNo, 1) over (PARTITION BY user_ID, topic_ID, item_id ORDER BY createdAt) prevAttemptNo
FROM StartedRank
) update cte 
  set AttemptNo=prevAttemptNo

您可以通过加入Welll来做到这一点

UPDATE A 
set AttemptNo=B.prevAttemptNo
FROM StartedRank A
JOIN (SELECT *,
    LAG(AttemptNo, 1) over (PARTITION BY user_ID, topic_ID, item_id ORDER BY createdAt) prevAttemptNo
    FROM StartedRank) B
    ON A.AttemptNo = B.AttemptNo