SQLのデータベーステーブルから上位nを除くすべてを削除します


85

SQLのテーブルからすべての行を削除し、n個の行を一番上に保持するための最良の方法は何ですか?

回答:


80
DELETE FROM Table WHERE ID NOT IN (SELECT TOP 10 ID FROM Table)

編集:

トップ10クエリが各行に対して実行されるため、Chrisはパフォーマンスに大きな影響を与えます。これが1回限りのことであれば、それほど大きな問題ではないかもしれませんが、一般的なことであれば、私はそれを詳しく調べました。


4
誰かが一般的に上位n行を除くすべてを削除する必要がある場合、私は彼らが心配すべきより大きな問題を抱えていると主張します。
ダニエルシャファー

6
一時テーブルを手動で作成するか(これがまれな操作であると想定)、DELETE FROM Table WHERE ID NOT IN (SELECT id FROM (SELECT TOP 10 ID FROM Table) AS x)MySQLに一時テーブルを作成させるようにクエリを作成することで、サブクエリのパフォーマンスの問題を解決できることに注意してください。
Michael Mior 2011

ありがとうございました。それは命の恩人でした:)
Si8 2014

1
サブクエリは複数回実行されますが、本当ですか?stackoverflow.com/questions/18790796/...
djluis

5
@ DanielSchafferデータベースやビジネスロジックの問題が発生したようには聞こえません。完全に通常の保持ポリシーのように聞こえます。
hejazzman 2017年

33

一時テーブルまたはテーブル変数に保持する行のセットのID列を選択します。次に、一時テーブルに存在しないすべての行を削除します。別のユーザーが言及した構文:

DELETE FROM Table WHERE ID NOT IN (SELECT TOP 10 ID FROM Table)

潜在的な問題があります。「SELECTTOP10」クエリは、テーブルの各行に対して実行されます。これは、パフォーマンスに大きな打撃を与える可能性があります。同じクエリを何度も繰り返さないようにします。

この構文は、元のSQLステートメントとしてリストしたものに基づいて機能するはずです。

create table #nuke(NukeID int)

insert into #nuke(Nuke) select top 1000 id from article

delete article where not exists (select 1 from nuke where Nukeid = id)

drop table #nuke

3
insert into #nuke(Nuke) ...おそらく次のようになります。insert into #nuke(NukeID) ...あなたはこれらの行を削除しないようにしようとしているので、また名前の核兵器が混乱しています。核兵器はおそらく削除されるという事実にちなんで名付けられています。
エルノ2016

12

MSSQLを使用しない使用者のための将来のリファレンス。

PostgreSQLではORDER BY、のLIMIT代わりにを使用しますTOP

DELETE FROM table
WHERE id NOT IN (SELECT id FROM table ORDER BY id LIMIT n);

MySQL-まあ...

エラー-このバージョンのMySQLは、「LIMIT&IN / ALL / ANY / SOMEサブクエリ」をまだサポートしていません

まだだと思います。


5

仮想テーブルを使用する方が、IN句や一時テーブルよりもはるかに優れていると思います。

DELETE 
    Product
FROM
    Product
    LEFT OUTER JOIN
    (
        SELECT TOP 10
            Product.id
        FROM
            Product
    ) TopProducts ON Product.id = TopProducts.id
WHERE
    TopProducts.id IS NULL

2

他のフレーバーについてはわかりませんが、MySQLDELETEではLIMITが許可されています。

保持したいn行が一番下になるように並べ替えることができる場合は、DELETE FROM table LIMITtablecount-nを実行できます。

編集

うーん。あなたの場合にうまくいくとすれば、私はCoryFoyの答えの方が好きだと思います。比較すると、私のやり方は少し不格好です。


2

これは実際には言語固有になりますが、SQLサーバーには次のようなものを使用する可能性があります。

declare @n int
SET @n = SELECT Count(*) FROM dTABLE;
DELETE TOP (@n - 10 ) FROM dTable

行の正確な数を気にしない場合は、常にあります

DELETE TOP 90 PERCENT FROM dTABLE;

1
これらはどちらも機能しません。質問は、テーブルの上位N行のみを保持する方法を尋ねます。これらの例は両方とも、下のN行のみを保持します。
クリス

1
MSSQLで正常に動作します。並べ替えを追加して、上部ではなく下部を削除しますか?
meanGreen 2015

2

これが私がそれをした方法です。この方法はより速く、より簡単です。

OFFSETコマンドを使用して、MSSQLのデータベーステーブルから上位nを除くすべてを削除します

WITH CTE AS
    (
    SELECT  ID
    FROM    dbo.TableName
    ORDER BY ID DESC
    OFFSET 11 ROWS
    )
DELETE CTE;

ID並べ替える列に置き換えます。後のOFFSET番号を、削除する行の数に置き換えます。DESCまたはASC-あなたのケースに合ったものを選択してください。


この場合、オフセットしたい行数はオフセットされませんか?
NapkinBob

@NapkinBobはい。
ハーベイ

0

以下のテクニックを使って解決します。この例では、各行にIDを持つ記事テーブルが必要です。

Delete article where id not in (select top 1000 id from article)

編集:私自身の質問に答えるには遅すぎます...


0

リファクタリング?

Delete a From Table a Inner Join (
    Select Top (Select Count(tableID) From Table) - 10) 
        From Table Order By tableID Desc
) b On b.tableID = A.tableID

編集:クエリアナライザーで両方を試しました、現在の答えは断食されています(いまいましいorder by ...)


0

より良い方法は、必要な行を別のテーブルに挿入し、元のテーブルを削除してから、新しいテーブルの名前を変更して、古いテーブルと同じ名前にすることです。


なぜそれが良いのですか?もっと早く?実行するには、いくつかの追加コマンドが必要です。
MeanGreen 2015

0

TOPすべての行に対して式を実行しないようにするためのトリックがあります。と組み合わせTOPて、維持したいものをMAX取得できMaxIdます。次に、より大きいものをすべて削除しますMaxId

-- Declare Variable to hold the highest id we want to keep. 
DECLARE @MaxId as int = (
SELECT MAX(temp.ID)
FROM (SELECT TOP 10 ID FROM table ORDER BY ID ASC) temp
)

-- Delete anything greater than MaxId. If MaxId is null, there is nothing to delete.
IF @MaxId IS NOT NULL
    DELETE FROM table WHERE ID > @MaxId

注:適切な結果が照会されるようORDER BYに宣言するときに使用することが重要MaxIdです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.