删除除了TOP 1

Tom*_*ter 4 sql t-sql sql-server sql-server-2005

有没有办法删除表中除一个(随机)行之外的所有行,而不在DELETE语句中指定任何列名?

我正在尝试做这样的事情:

CREATE TABLE [dbo].[DeleteExceptTop1]([Id] INT)
INSERT [dbo].[DeleteExceptTop1] SELECT 1
INSERT [dbo].[DeleteExceptTop1] SELECT 2
INSERT [dbo].[DeleteExceptTop1] SELECT 3

SELECT * FROM [dbo].[DeleteExceptTop1]

DELETE
FROM [dbo].[DeleteExceptTop1]
EXCEPT
SELECT TOP 1 * FROM [dbo].[DeleteExceptTop1]

SELECT * FROM [dbo].[DeleteExceptTop1]
Run Code Online (Sandbox Code Playgroud)

决赛SELECT应该产生一行(可以是三行中的任何一行).

Mar*_*ith 6

;WITH CTE AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT newid())) AS RN
FROM [dbo].[DeleteExceptTop1]
)
DELETE FROM CTE
WHERE RN > 1
Run Code Online (Sandbox Code Playgroud)

或类似于@ abatishchev的答案,但在排序中有更多种类,并避免弃用的结构.

DECLARE @C INT
SELECT @C = COUNT(*) - 1 
FROM [dbo].[DeleteExceptTop1]

IF @c > 0
BEGIN
WITH CTE AS
(
SELECT TOP(@C) *
FROM [dbo].[DeleteExceptTop1]
ORDER BY NEWID()
)
DELETE FROM CTE;
END
Run Code Online (Sandbox Code Playgroud)

或者是使用EXCEPT和假设没有重复行的最终方式,并且所有列都是与EXCEPT运算符兼容的数据类型

/*Materialise TOP 1 to ensure only evaluated once*/
SELECT TOP(1) * 
INTO #T
FROM [dbo].[DeleteExceptTop1]
ORDER BY NEWID()

;WITH CTE AS
(
SELECT *
FROM [dbo].[DeleteExceptTop1] T1
WHERE EXISTS(
             SELECT *
             FROM #T
             EXCEPT
             SELECT T1.*)
)
DELETE FROM CTE;

DROP TABLE #T
Run Code Online (Sandbox Code Playgroud)