SQL의 데이터베이스 테이블에서 상위 n 개를 제외한 모두 삭제


85

SQL의 테이블에서 모든 행을 삭제하고 n 개의 행을 맨 위에 유지하는 가장 좋은 방법은 무엇입니까?

답변:


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

편집하다:

Chris는 각 행에 대해 TOP 10 쿼리가 실행되기 때문에 좋은 성능 저하를 가져옵니다. 일회성이라면 그렇게 크지 않을 수도 있지만, 일반적인 일이라면 자세히 살펴 보았습니다.


4
누군가가 일반적으로 상위 n 개 행을 제외하고 모두 삭제해야한다면 걱정할 더 큰 문제가 있다고 생각합니다.
Daniel Schaffer

6
임시 테이블을 수동으로 생성하거나 (빈번하지 않은 작업이라고 가정) 쿼리 DELETE FROM Table WHERE ID NOT IN (SELECT id FROM (SELECT TOP 10 ID FROM Table) AS x)를 작성하여 MySQL 이 임시 테이블을 생성하도록하여 하위 쿼리 성능 문제를 해결할 수 있습니다 .
Michael Mior 2011

감사합니다. 그것은 생명의 은인이었습니다 :)
Si8

1
하위 쿼리가 여러 번 실행됩니다. 사실입니까? stackoverflow.com/questions/18790796/…
djluis

5
@ Daniel Schaffer DB 또는 비즈니스 로직 문제가있는 것처럼 들리지 않습니다. 완전히 정상적인 보존 정책처럼 들립니다.
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하고 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

다른 맛에 대해서는 모르지만 MySQL DELETE 는 LIMIT를 허용합니다.

유지하려는 n 행이 맨 아래에 오도록 주문할 수 있다면 DELETE FROM table 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 개 행만 유지합니다.
Chris

1
MSSQL에서 잘 작동합니다. 정렬을 추가하여 상단 대신 하단을 삭제 하시겠습니까?
MeanGreen

2

내가 한 방법은 다음과 같습니다. 이 방법은 더 빠르고 간단합니다.

OFFSET 명령을 사용하여 MS SQL의 데이터베이스 테이블에서 상위 n 개를 제외한 모두 삭제

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

아래 기술을 사용하여 해결할 것입니다. 이 예 에서는 각 행에 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

편집 : 쿼리 분석기에서 둘 다 시도해 보았습니다. 현재 답변은 금식입니다 (젠장 ...)


0

더 나은 방법은 원하는 행을 다른 테이블에 삽입하고 원래 테이블을 삭제 한 다음 새 테이블의 이름을 변경하여 이전 테이블과 동일한 이름을 갖는 것입니다.


그게 더 나은 이유는 무엇입니까? 더 빨리? 수행하려면 몇 가지 추가 명령이 필요합니다.
MeanGreen

0

TOP모든 행에 대해 표현식을 실행하지 않는 트릭이 있습니다. 우리는 결합 할 수 있습니다 TOPMAX얻기 위해 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.