4

DELETEステートメントに列名を指定せずに、1つの(ランダムな)行を除くテーブル内のすべての行を削除する方法はありますか?

私はこのようなことをしようとしています:

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は1つの行を生成する必要があります(3つのいずれかである可能性があります)。

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

EXCEPTDISTINCT行の値を比較することで機能します。

編集:主キーを指定できる 場合、これは簡単なことです。「ランダム」選択またはDELETE「ランダム」選択の PKを簡単に指定できます。<> NOT IN

編集:どうやら、列名を指定する必要性について私は間違っているようです。割り当てられた .. を使用してそれを行うことができますがコメントで議論されたROW_NUMBER使用法を参照しているため、回答を削除するつもりはありません。からそのような列名を派生させずにそれを行うことEXCEPTできませんROW_NUMBER

于 2012-05-30T16:19:10.540 に答える
1

私はそれが答えられたことを知っていますが、どうですか?

DELETE 
FROM [dbo].[DeleteExceptTop1]
Where Id not in (
SELECT TOP 1 * FROM [dbo].[DeleteExceptTop1])
于 2012-07-31T08:34:27.060 に答える
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 に答える