SQL Server:根据当前行中的值删除以前的行

SQL Server:根据当前行中的值删除以前的行,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个包含以下列的表格:作者姓名、国家、状态 Author_name country status ------------------------------------------- 1 Author - 1 Country - 1 name remove 2 Author - 2 Country - 2 name done 3 Author - 3 Country - 3 name done 4 Author - 4

我有一个包含以下列的表格:作者姓名、国家、状态

    Author_name       country       status
-------------------------------------------
1   Author - 1  Country - 1 name    remove
2   Author - 2  Country - 2 name    done
3   Author - 3  Country - 3 name    done
4   Author - 4  Country - 4 name    done
5   Author - 5  Country - 5 name    done
6   Author - 6  Country - 6 name    remove
7   Author - 7  Country - 7 name    remove
8   Author - 8  Country - 8 name    done
9   Author - 9  Country - 9 name    remove
10  Author - 10 Country - 10 name   done
预期功能:当遇到“删除”时,必须删除该行并删除其上方的行

如果“删除”连续出现,则必须删除顶部的许多行。 “删除”的位置和记录数不是常数

运行SQL脚本后,上表的输出应为:

     Author_name      country        status
-------------------------------------------
2    Author - 2  Country - 2 name    done
3    Author - 3  Country - 3 name    done
10   Author - 10 Country - 10 name   done
希望你能理解其中的逻辑

我尝试使用滞后、游标和其他一些工具。现在我正在尝试while循环。请帮我做这个。这是我的最新代码

我的数据库是SQL Server,目前我正在使用在线编译器:

如果你反向工作,你可以在“删除”为-1,“完成”为+1的地方加总分数

然后,您只希望保留仍在向后工作的行,该行的分数高于迄今为止的分数

    Author_name   Country             Status    Score   PreviousMax
--------------------------------------------------------------------
1   Author - 1    Country - 1 name    remove     2      3
2   Author - 2    Country - 2 name    done       3      2    <- KEEP
3   Author - 3    Country - 3 name    done       2      1    <- KEEP 
4   Author - 4    Country - 4 name    done       1      1
5   Author - 5    Country - 5 name    done       0      1
6   Author - 6    Country - 6 name    remove    -1      1
7   Author - 7    Country - 7 name    remove     0      1
8   Author - 8    Country - 8 name    done       1      1
9   Author - 9    Country - 9 name    remove     0      1
10  Author - 10   Country - 10 name   done       1      NULL <- KEEP
这也会让你

WITH
  scored_rows AS
(
  SELECT
    *,
    SUM(CASE WHEN status = 'remove' THEN -1 ELSE 1 END)
      OVER (ORDER BY timestamp DESC, id DESC)
        AS score
  FROM
    tblAuthors
),
  checked_scored_rows AS
(
  SELECT
    *,
    MAX(score)
      OVER (ORDER BY timestamp DESC, id DESC
                ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
           )
             AS previous_max_score
  FROM
    scored_rows
)
DELETE
  tblAuthors
FROM
  checked_scored_rows
WHERE
      checked_scored_rows.id     = tblAuthors.id
  AND checked_scored_rows.score <= COALESCE(checked_scored_rows.previous_max_score, 0)
我相信这说明了你想要什么:

如果你反向工作,你可以在“删除”为-1,“完成”为+1的地方加总分数

然后,您只希望保留仍在向后工作的行,该行的分数高于迄今为止的分数

    Author_name   Country             Status    Score   PreviousMax
--------------------------------------------------------------------
1   Author - 1    Country - 1 name    remove     2      3
2   Author - 2    Country - 2 name    done       3      2    <- KEEP
3   Author - 3    Country - 3 name    done       2      1    <- KEEP 
4   Author - 4    Country - 4 name    done       1      1
5   Author - 5    Country - 5 name    done       0      1
6   Author - 6    Country - 6 name    remove    -1      1
7   Author - 7    Country - 7 name    remove     0      1
8   Author - 8    Country - 8 name    done       1      1
9   Author - 9    Country - 9 name    remove     0      1
10  Author - 10   Country - 10 name   done       1      NULL <- KEEP
这也会让你

WITH
  scored_rows AS
(
  SELECT
    *,
    SUM(CASE WHEN status = 'remove' THEN -1 ELSE 1 END)
      OVER (ORDER BY timestamp DESC, id DESC)
        AS score
  FROM
    tblAuthors
),
  checked_scored_rows AS
(
  SELECT
    *,
    MAX(score)
      OVER (ORDER BY timestamp DESC, id DESC
                ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
           )
             AS previous_max_score
  FROM
    scored_rows
)
DELETE
  tblAuthors
FROM
  checked_scored_rows
WHERE
      checked_scored_rows.id     = tblAuthors.id
  AND checked_scored_rows.score <= COALESCE(checked_scored_rows.previous_max_score, 0)

我相信这说明了您想要的:

SQL中的数据集是显式无序的。上面没有一排。您需要一个或多个列,可以在ORDER BY中使用这些列来声明订单。你有这样的专栏吗?例如插入行时的时间戳?Hi@MatBailie是的,有一个标识列,希望我们可以使用相同的。标识列不保证有序,一行的标识值可能低于预先存在的行。最佳实践是从不从标识列推断任何内容,而只将其用作唯一标识符。您还有其他列吗?@MatBailie..感谢您的回复..我目前正在开发DB,我可以添加时间戳列。希望这能解决顺序问题。@MatBailie timestamp列被添加了……我仍在试图弄清楚删除过程。SQL中的数据集是显式无序的。上面没有一排。您需要一个或多个列,可以在ORDER BY中使用这些列来声明订单。你有这样的专栏吗?例如插入行时的时间戳?Hi@MatBailie是的,有一个标识列,希望我们可以使用相同的。标识列不保证有序,一行的标识值可能低于预先存在的行。最佳实践是从不从标识列推断任何内容,而只将其用作唯一标识符。您还有其他列吗?@MatBailie..感谢您的回复..我目前正在开发DB,我可以添加时间戳列。希望能解决订单问题。@MatBailie timestamp列被添加……我仍在试图找出删除过程。
WITH
  scored_rows AS
(
  SELECT
    *,
    SUM(CASE WHEN status = 'remove' THEN -1 ELSE 1 END)
      OVER (ORDER BY timestamp DESC, id DESC)
        AS score
  FROM
    tblAuthors
),
  checked_scored_rows AS
(
  SELECT
    *,
    MAX(score)
      OVER (ORDER BY timestamp DESC, id DESC
                ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
           )
             AS previous_max_score
  FROM
    scored_rows
)
SELECT
  *
FROM
  checked_scored_rows
WHERE
  score > COALESCE(previous_max_score, 0)
;
WITH
  scored_rows AS
(
  SELECT
    *,
    SUM(CASE WHEN status = 'remove' THEN -1 ELSE 1 END)
      OVER (ORDER BY timestamp DESC, id DESC)
        AS score
  FROM
    tblAuthors
),
  checked_scored_rows AS
(
  SELECT
    *,
    MAX(score)
      OVER (ORDER BY timestamp DESC, id DESC
                ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
           )
             AS previous_max_score
  FROM
    scored_rows
)
DELETE
  tblAuthors
FROM
  checked_scored_rows
WHERE
      checked_scored_rows.id     = tblAuthors.id
  AND checked_scored_rows.score <= COALESCE(checked_scored_rows.previous_max_score, 0)