Eliminar todos menos los n primeros de la tabla de la base de datos en SQL

85

¿Cuál es la mejor manera de eliminar todas las filas de una tabla en sql pero mantener n número de filas en la parte superior?

Riri
fuente

Respuestas:

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

Editar:

Chris muestra un buen resultado de rendimiento ya que la consulta TOP 10 se ejecutaría para cada fila. Si esto es algo único, entonces puede que no sea tan importante, pero si es algo común, entonces lo miré más de cerca.

Cory Foy
fuente
4
Si alguien necesita eliminar todas las filas excepto las n primeras, diría que tiene problemas más importantes de los que preocuparse.
Daniel Schaffer
6
Solo una nota de que puede resolver el problema de rendimiento de la subconsulta creando una tabla temporal manualmente (asumiendo que esta es una operación poco frecuente) o escribiendo la consulta DELETE FROM Table WHERE ID NOT IN (SELECT id FROM (SELECT TOP 10 ID FROM Table) AS x)para forzar a MySQL a crear una tabla temporal.
Michael Mior
Gracias. Eso fue un salvavidas :)
Si8
1
La subconsulta se ejecuta varias veces, ¿es cierto? stackoverflow.com/questions/18790796/…
djluis
5
@ Daniel Schaffer No parece que tuvieran ningún problema de lógica empresarial o de base de datos. Suena como una política de retención totalmente normal.
Hejazzman
33

Seleccionaría la (s) columna (s) de ID el conjunto de filas que desea mantener en una tabla temporal o variable de tabla. Luego, elimine todas las filas que no existen en la tabla temporal. La sintaxis mencionada por otro usuario:

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

Tiene un problema potencial. La consulta "SELECT TOP 10" se ejecutará para cada fila de la tabla, lo que podría ser un gran éxito en el rendimiento. Quiere evitar hacer la misma consulta una y otra vez.

Esta sintaxis debería funcionar, según lo que enumeró como su declaración SQL original:

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
Chris Miller
fuente
3
insert into #nuke(Nuke) ...probablemente debería ser: insert into #nuke(NukeID) ...Además, el nombre nuke es confuso porque está tratando de NO eliminar estas filas. nuke probablemente lleva el nombre del hecho de que será eliminado.
Erno
12

Referencia futura para quienes no utilizan MS SQL.

En PostgreSQL use ORDER BYy en LIMITlugar de TOP.

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

MySQL - bueno ...

Error : esta versión de MySQL aún no admite la subconsulta 'LIMIT & IN / ALL / ANY / SOME'

Supongo que todavía no.

Simurr
fuente
5

Creo que usar una tabla virtual sería mucho mejor que una cláusula IN o una tabla temporal.

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
Tim Wilson
fuente
2

No sé sobre otros sabores, pero MySQL DELETE permite LIMIT.

Si pudiera ordenar las cosas de modo que las n filas que desea mantener estén en la parte inferior, entonces podría hacer un DELETE FROM table LIMIT tablecount-n.

Editar

Oooo. Creo que me gusta más la respuesta de Cory Foy , asumiendo que funciona en tu caso. Mi camino se siente un poco torpe en comparación.

Mark Biek
fuente
2

Esto realmente va a ser específico del idioma, pero probablemente usaría algo como lo siguiente para el servidor SQL.

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

si no le importa el número exacto de filas, siempre hay

DELETE TOP 90 PERCENT FROM dTABLE;
Noé
fuente
1
Ninguno de estos funciona. La pregunta pregunta cómo mantener solo las N filas superiores en una tabla. Ambos ejemplos mantienen solo las N filas inferiores.
Chris
1
Funciona bien en MSSQL. ¿Simplemente agregue una clasificación para eliminar la parte inferior en lugar de la superior?
MeanGreen
2

Así es como lo hice. Este método es más rápido y sencillo:

Elimine todos menos los primeros n de la tabla de la base de datos en MS SQL usando el comando OFFSET

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

Reemplazar IDcon la columna por la que desea ordenar. Reemplace el número después OFFSETcon el número de filas que desea eliminar. Elija DESCo ASC- lo que se adapte a su caso.

Harvey
fuente
¿No sería la compensación el número de filas que desea mantener en este caso?
NapkinBob
@NapkinBob Sí.
Harvey
0

Lo resolvería usando la técnica siguiente. El ejemplo espera una tabla de artículos con una identificación en cada fila.

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

Editar: Demasiado lento para responder mi propia pregunta ...

Riri
fuente
0

¿Refactorizado?

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

editar: probé ambos en el analizador de consultas, la respuesta actual es en ayunas (maldita orden por ...)

Shawn
fuente
0

Una mejor manera sería insertar las filas que SI desea en otra tabla, soltar la tabla original y luego cambiar el nombre de la nueva tabla para que tenga el mismo nombre que la tabla anterior

SQLMenace
fuente
¿Por qué es mejor? ¿Más rápido? Requiere un par de comandos adicionales para lograrlo.
MeanGreen
0

Tengo un truco para evitar ejecutar la TOPexpresión para cada fila. Podemos combinar TOPcon MAXpara obtener el MaxIdque queremos mantener. Luego, simplemente borramos todo lo que sea mayor que 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

Nota: Es importante utilizarlo ORDER BYal declarar MaxIdpara asegurarse de que se consultan los resultados adecuados.

clamchoda
fuente