Объединение Dense_Rank () и Lag () в одном столбце - PullRequest
0 голосов
/ 08 июля 2019

Я генерирую числа попыток на основе User ID, Topic ID, Item ID и Status.

К сожалению, функция 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 Ответ

1 голос
/ 08 июля 2019

используйте 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

Вы можете сделать это, присоединившись, а также

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
...