ลบทั้งหมดยกเว้น n อันดับแรกจากตารางฐานข้อมูลใน SQL


86

วิธีใดที่ดีที่สุดในการลบแถวทั้งหมดจากตารางใน sql แต่เพื่อให้ n จำนวนแถวอยู่ด้านบน

คำตอบ:


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

แก้ไข:

Chris นำเสนอผลงานที่ได้รับความนิยมเนื่องจากคำค้นหา TOP 10 จะถูกเรียกใช้สำหรับแต่ละแถว หากนี่เป็นเพียงครั้งเดียวมันอาจจะไม่ใช่เรื่องใหญ่ แต่ถ้าเป็นเรื่องธรรมดาฉันก็ลองมองใกล้ ๆ


6
โปรดทราบว่าคุณสามารถแก้ไขปัญหาประสิทธิภาพของแบบสอบถามย่อยผ่านการสร้างตารางชั่วคราวด้วยตนเอง (สมมติว่าเป็นการดำเนินการที่ไม่บ่อยนัก) หรือเขียนแบบสอบถามDELETE FROM Table WHERE ID NOT IN (SELECT id FROM (SELECT TOP 10 ID FROM Table) AS x)เพื่อบังคับให้ MySQL สร้างตารางชั่วคราว
Michael Mior

ขอขอบคุณ. นั่นคือการช่วยชีวิต :)
Si8

1
แบบสอบถามย่อยทำงานหลายครั้งจริงหรือไม่? stackoverflow.com/questions/18790796/…
djluis

5
@ Daniel Schaffer ดูเหมือนพวกเขาจะมีปัญหาด้านฐานข้อมูลหรือตรรกะทางธุรกิจ ดูเหมือนนโยบายการเก็บรักษาปกติโดยสิ้นเชิง
Hejazzman

33

ฉันจะเลือกคอลัมน์ ID ชุดของแถวที่คุณต้องการเก็บไว้ในตารางชั่วคราวหรือตัวแปรตาราง จากนั้นลบแถวทั้งหมดที่ไม่มีอยู่ในตารางชั่วคราว ไวยากรณ์ที่กล่าวถึงโดยผู้ใช้รายอื่น:

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

มีปัญหาที่อาจเกิดขึ้น ระบบจะเรียกใช้การสืบค้น "SELECT TOP 10" สำหรับแต่ละแถวในตารางซึ่งอาจเป็นผลดีอย่างมาก คุณต้องการหลีกเลี่ยงการสร้างข้อความค้นหาเดิมซ้ำแล้วซ้ำเล่า

ไวยากรณ์นี้ควรใช้งานได้ตามสิ่งที่คุณระบุไว้เป็นคำสั่ง 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) ...ชื่อ nuke ยังสับสนเนื่องจากคุณพยายามที่จะไม่ลบแถวเหล่านี้ nuke อาจตั้งชื่อตามความจริงที่ว่ามันจะถูกลบ
Erno

12

การอ้างอิงในอนาคตสำหรับผู้ใช้ที่ไม่ได้ใช้ MS SQL

ใน PostgreSQL การใช้งานORDER BYและการแทนLIMITTOP

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

MySQL - อืม ...

ข้อผิดพลาด - MySQL เวอร์ชันนี้ยังไม่รองรับ 'LIMIT & IN / ALL / ANY / SOME subquery'

ยังไม่ฉันเดา


5

ฉันคิดว่าการใช้ตารางเสมือนจะดีกว่าตาราง IN-clause หรือ temp

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

ฉันไม่รู้เกี่ยวกับรสชาติอื่น ๆ แต่ MySQL DELETEอนุญาต LIMIT

หากคุณสามารถเรียงลำดับสิ่งต่างๆเพื่อให้ n แถวที่คุณต้องการเก็บไว้ที่ด้านล่างคุณสามารถทำการลบจากตาราง LIMIT tablecount-n

แก้ไข

Oooo. ฉันคิดว่าฉันชอบคำตอบของ Cory Foyดีกว่าโดยสมมติว่าใช้ได้ในกรณีของคุณ ทางของฉันรู้สึกอึดอัดเล็กน้อยเมื่อเปรียบเทียบ


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

2

นี่คือวิธีที่ฉันทำ วิธีนี้เร็วกว่าและง่ายกว่า:

ลบทั้งหมดยกเว้นด้านบนจากตารางฐานข้อมูลใน MS SQL โดยใช้คำสั่ง OFFSET

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

แทนที่IDด้วยคอลัมน์ที่คุณต้องการจัดเรียง แทนที่ตัวเลขหลังOFFSETด้วยจำนวนแถวที่คุณต้องการเก็บไว้ เลือกDESCหรือASC- อะไรก็ได้ที่เหมาะกับกรณีของคุณ


จะไม่หักล้างจำนวนแถวที่คุณต้องการเก็บไว้ในกรณีนี้หรือไม่?
NapkinBob

@NapkinBob ใช่ค่ะ
Harvey

0

ฉันจะแก้ปัญหาโดยใช้เทคนิคด้านล่าง ตัวอย่างคาดหวังไฟล์ตารางบทความที่มีรหัสในแต่ละแถว

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

แก้ไข: ช้าเกินไปที่จะตอบคำถามของตัวเอง ...


0

Refactored?

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

แก้ไข: ลองใช้ทั้งสองอย่างในตัววิเคราะห์แบบสอบถามคำตอบปัจจุบันถูกยึด (เรียงลำดับโดย ... )


0

วิธีที่ดีกว่าคือการแทรกแถวที่คุณต้องการลงในตารางอื่นวางตารางเดิมแล้วเปลี่ยนชื่อตารางใหม่เพื่อให้มีชื่อเดียวกันกับตารางเก่า


ทำไมถึงดีกว่า? เร็วขึ้น? ต้องใช้คำสั่งพิเศษสองสามคำเพื่อให้สำเร็จ
MeanGreen

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.