SQL'deki veritabanı tablosundan üst n hariç tümünü sil


86

SQL'deki bir tablodan tüm satırları silmenin ancak n sayıda satırı en üstte tutmanın en iyi yolu nedir?

Yanıtlar:


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

Düzenle:

Her satır için İLK 10 sorgusu çalıştırılacağından, Chris iyi bir performans isabeti getiriyor. Bu tek seferlik bir şeyse, o kadar büyük bir anlaşma olmayabilir, ancak ortak bir şeyse, ona daha yakından baktım.


6
Alt sorgu performans sorununu manuel olarak geçici bir tablo oluşturarak (bunun sık olmayan bir işlem olduğunu varsayarak) veya DELETE FROM Table WHERE ID NOT IN (SELECT id FROM (SELECT TOP 10 ID FROM Table) AS x)MySQL'i geçici bir tablo oluşturmaya zorlamak için sorgu yazarak çözebileceğinizi unutmayın .
Michael Mior

Teşekkür ederim. Bu bir hayat kurtarıcıydı :)
Si8

1
Alt sorgu birden çok kez çalıştırılıyor, doğru mu? stackoverflow.com/questions/18790796/…
djluis

5
@ Daniel Schaffer herhangi bir db veya iş mantığı sorunu varmış gibi gelmiyor. Tamamen normal bir saklama politikası gibi görünüyor.
Hejazzman

33

Geçici bir tablo veya tablo değişkeninde tutmak istediğiniz satır kümesini ID sütun (lar) ını seçerdim. Daha sonra geçici tabloda bulunmayan tüm satırları silin. Başka bir kullanıcı tarafından bahsedilen sözdizimi:

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

Olası bir sorunu var. "İLK 10 SEÇİN" sorgusu tablodaki her satır için yürütülür ve bu büyük bir performans artışı olabilir. Aynı sorguyu defalarca yapmaktan kaçınmak istersiniz.

Bu sözdizimi, orijinal SQL deyiminiz olarak listelediğinize göre çalışmalıdır:

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) ...muhtemelen şöyle olmalıdır: insert into #nuke(NukeID) ...Ayrıca nuke adı kafa karıştırıcıdır çünkü bu satırları SİLMEMEYE çalışıyorsunuz. Nuke, muhtemelen silineceği gerçeğinden sonra adlandırılmıştır.
Erno

12

MS SQL kullanmayan kullanıcılar için gelecekteki referans.

PostgreSQL'de ORDER BYve LIMITyerine TOP.

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

MySQL - iyi ...

Hata - MySQL'in bu sürümü henüz 'LIMIT & IN / ALL / ANY / SOME alt sorgusunu' desteklemiyor

Henüz değil sanırım.


5

Sanal bir tablo kullanmanın bir IN cümlesi veya geçici tablodan çok daha iyi olacağını düşünüyorum.

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

Diğer tatları bilmiyorum ama MySQL DELETE LIMIT'e izin veriyor.

Bir şeyleri, tutmak istediğiniz n satır en altta olacak şekilde sıralayabilseydiniz, o zaman bir DELETE FROM tablecount-n yapabilirsiniz.

Düzenle

Oooo. Senin durumunda işe yaradığını varsayarak, Cory Foy'un cevabını daha çok sevdiğimi düşünüyorum . Karşılaştırıldığında yolum biraz hantal geliyor.


2

Bu gerçekten dile özgü olacak, ancak SQL sunucusu için muhtemelen aşağıdaki gibi bir şey kullanacağım.

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

tam satır sayısı umurunuzda değilse, her zaman

DELETE TOP 90 PERCENT FROM dTABLE;

1
Bunların hiçbiri işe yaramıyor. Soru, bir tabloda yalnızca ilk N satırın nasıl tutulacağını sorar. Bu örneklerin her ikisi de yalnızca en alttaki N satırı tutar.
Chris

1
MSSQL'de iyi çalışıyor. Üst yerine altını silmek için bir sıralama mı ekleyeceksiniz?
MeanGreen

2

İşte böyle yaptım. Bu yöntem daha hızlı ve daha basittir:

OFFSET komutunu kullanarak MS SQL'deki veritabanı tablosundan üst n hariç tümünü sil

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

IDSıralamak istediğiniz sütunla değiştirin . Saklamak OFFSETistediğiniz satır sayısının ardındaki sayıyı değiştirin . DESCVeya ASC- durumunuza uygun olanı seçin .


Bu durumda tutmak istediğiniz satır sayısı ofset olmaz mı?
NapkinBob

@NapkinBob Evet.
Harvey

0

Aşağıdaki tekniği kullanarak çözerdim. Örnek , her satırında bir id bulunan bir makale tablosu beklemektedir .

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

Düzenleme: Kendi sorumu cevaplamak için çok yavaş ...


0

Yeniden mi düzenlendi?

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

düzenleme: her ikisini de sorgu analizöründe denedi, mevcut cevap hızlı (lanet sipariş ...)


0

Daha iyi bir yol, İSTEDİĞİNİZ satırları başka bir tabloya eklemek, orijinal tabloyu bırakmak ve ardından yeni tabloyu eski tablo ile aynı ada sahip olacak şekilde yeniden adlandırmaktır.


Bu neden daha iyi? Daha hızlı? Gerçekleştirmek için birkaç ekstra komut gerektirir.
MeanGreen

0

TOPHer satır için ifadeyi çalıştırmaktan kaçınmam gereken bir numaram var . Biz birleştirebilirsiniz TOPile MAXalmak için MaxIdbiz devam etmek istiyorum. Sonra daha büyük olan her şeyi siliyoruz 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

Not: Uygun sonuçların sorgulandığından emin olmak için ORDER BYbeyan ederken kullanılması önemlidir MaxId.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.