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)