采访中被问到的一个问题是,
一张表有 100 条记录。其中 50 个是重复的。是否可以通过单个查询从表中删除重复记录以及选择并显示剩余的 50 条记录。
这可以在单个 SQL 查询中实现吗?
谢谢
国民账户体系
采访中被问到的一个问题是,
一张表有 100 条记录。其中 50 个是重复的。是否可以通过单个查询从表中删除重复记录以及选择并显示剩余的 50 条记录。
这可以在单个 SQL 查询中实现吗?
谢谢
国民账户体系
使用 SQL Server 你会使用这样的东西
DECLARE @Table TABLE (ID INTEGER, PossibleDuplicate INTEGER)
INSERT INTO @Table VALUES (1, 100)
INSERT INTO @Table VALUES (2, 100)
INSERT INTO @Table VALUES (3, 200)
INSERT INTO @Table VALUES (4, 200)
DELETE FROM @Table
OUTPUT Deleted.*
FROM @Table t
INNER JOIN (
SELECT ID = MAX(ID)
FROM @Table
GROUP BY PossibleDuplicate
HAVING COUNT(*) > 1
) d ON d.ID = t.ID
OUTPUT语句显示被删除的记录。
更新:
上面的查询将删除重复项并为您提供已删除的行,而不是保留的行。如果这对您很重要(总而言之,剩余的 50 行应该与 50 删除的行相同),您可以使用SQL Server 的 2008 MERGE语法来实现这一点。
Lieven's Answer很好地解释了如何输出已删除的行。我想补充两点:
如果你想对输出做更多的事情而不是显示它,你可以指定OUTPUT INTO @Tbl
(在哪里@Tbl
是你在删除之前声明的 table-var);
使用MAX
、MIN
或任何其他聚合只能处理每组一个重复的行。如果您可能有许多重复项,以下 SQL Server 2005+ 代码将有助于做到这一点:
;WITH Duplicates AS
(
SELECT
ID,
ROW_NUMBER() OVER (PARTITION BY DupeColumn ORDER BY ID) AS RowNum
)
DELETE FROM MyTable
OUTPUT deleted.*
WHERE ID IN
(
SELECT ID
FROM Duplicates
WHERE RowNum > 1
)
听起来不太可能,至少在 ANSI SQL 中,因为 delete 只返回已删除行数的计数。