4

有没有办法删除表中除一个(随机)行之外的所有行,而不在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]

最后SELECT应该产生一行(可以是三行中的任何一行)。

4

6 回答 6

6
;WITH CTE AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT newid())) AS RN
FROM [dbo].[DeleteExceptTop1]
)
DELETE FROM CTE
WHERE RN > 1

或类似于@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

或者使用并假设没有重复行并且所有列的数据类型与运算符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
于 2012-05-30T16:24:55.650 回答
3

尝试:

declare @c int
select @c = count(*) - 1 from [dbo].[DeleteExceptTop1]

IF @c > 0
BEGIN

set RowCount  @c

delete from [dbo].[DeleteExceptTop1]
END
于 2012-05-30T16:26:50.003 回答
2

不可以。
您需要使用列名(例如主键的名称)来标识要删除的行。

除了数据之外,“随机行”在 SQL 中没有任何意义。如果要删除某行以外的所有内容,则必须将该行与其他行区分开来DELETE

EXCEPT通过比较DISTINCT行中的值来工作。

编辑: 如果您可以指定主键,那么这是一件小事。您可以简单地DELETE将 PK<>您的“随机”选择 NOT IN“随机”选择放在哪里。

编辑:显然我对指定任何列名的需要是错误的,您可以使用分配的ROW_NUMBER.. 但我不会删除我的答案,因为它引用了您EXCEPT在评论中讨论的使用。如果_ _ROW_NUMBER

于 2012-05-30T16:19:10.540 回答
1

你可以做这样的事情(SQL 2008)

DECLARE @Original TABLE ([Id] INT)
INSERT INTO @Original(ID) VALUES(1)
INSERT INTO @Original(ID) VALUES(2)
INSERT INTO @Original(ID) VALUES(3)

SELECT * FROM @Original;

WITH CTE AS
(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS ROW, ID FROM @Original)
DELETE @Original
FROM @Original O
INNER JOIN CTE ON O.ID = CTE.ROW
WHERE ROW > 1

SELECT * FROM @Original
于 2012-05-30T16:25:45.330 回答
1

似乎最简单的答案可能是最好的。以下应该有效:

Declare @count int
Set @count=(Select count(*) from DeleteExceptTop1)-1
Delete top (@count) from DeleteExceptTop1
于 2012-06-15T00:05:02.377 回答
1

我知道它已被回答,但是呢?

DELETE 
FROM [dbo].[DeleteExceptTop1]
Where Id not in (
SELECT TOP 1 * FROM [dbo].[DeleteExceptTop1])
于 2012-07-31T08:34:27.060 回答