Qual é a melhor maneira de excluir todas as linhas de uma tabela no sql, mas manter n número de linhas no topo?
85
DELETE FROM Table WHERE ID NOT IN (SELECT TOP 10 ID FROM Table)
Editar:
Chris traz um bom resultado de desempenho, já que a consulta TOP 10 seria executada para cada linha. Se for uma coisa única, então pode não ser tão importante, mas se for uma coisa comum, então eu olhei mais de perto.
DELETE FROM Table WHERE ID NOT IN (SELECT id FROM (SELECT TOP 10 ID FROM Table) AS x)
para forçar o MySQL a criar uma tabela temporária.Eu selecionaria ID coluna (s) o conjunto de linhas que você deseja manter em uma tabela temporária ou variável de tabela. Em seguida, exclua todas as linhas que não existem na tabela temporária. A sintaxe mencionada por outro usuário:
DELETE FROM Table WHERE ID NOT IN (SELECT TOP 10 ID FROM Table)
Tem um problema potencial. A consulta "SELECT TOP 10" será executada para cada linha da tabela, o que pode ser um grande impacto no desempenho. Você deseja evitar fazer a mesma consulta repetidamente.
Essa sintaxe deve funcionar, com base no que você listou como sua instrução 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
fonte
insert into #nuke(Nuke) ...
provavelmente deveria ser:insert into #nuke(NukeID) ...
Além disso, o nome nuke é confuso porque você está tentando NÃO deletar essas linhas. nuke é provavelmente nomeado após o fato de que será excluído.Referência futura para quem não usa MS SQL.
No PostgreSQL, use
ORDER BY
e emLIMIT
vez deTOP
.DELETE FROM table WHERE id NOT IN (SELECT id FROM table ORDER BY id LIMIT n);
MySQL - bem ...
Acho que ainda não.
fonte
Acho que usar uma tabela virtual seria muito melhor do que uma cláusula IN ou uma tabela temporária.
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
fonte
Não sei sobre outros sabores, mas o MySQL DELETE permite LIMIT.
Se você pudesse ordenar as coisas de forma que as n linhas que deseja manter fiquem no final, você poderia fazer um DELETE FROM tabela LIMIT tablecount-n.
Editar
Oooo. Acho que gosto mais da resposta de Cory Foy , presumindo que funcione no seu caso. Meu caminho parece um pouco desajeitado em comparação.
fonte
Isso realmente vai ser específico do idioma, mas provavelmente usaria algo como o seguinte para o servidor SQL.
declare @n int SET @n = SELECT Count(*) FROM dTABLE; DELETE TOP (@n - 10 ) FROM dTable
se você não se preocupa com o número exato de linhas, sempre há
DELETE TOP 90 PERCENT FROM dTABLE;
fonte
Aqui está como eu fiz. Este método é mais rápido e simples:
Exclua tudo, exceto n superior da tabela de banco de dados em MS SQL usando o comando OFFSET
WITH CTE AS ( SELECT ID FROM dbo.TableName ORDER BY ID DESC OFFSET 11 ROWS ) DELETE CTE;
Substitua
ID
pela coluna pela qual você deseja classificar. Substitua o número a seguirOFFSET
pelo número de linhas que deseja manter. EscolhaDESC
ouASC
- o que for adequado ao seu caso.fonte
Eu iria resolver isso usando a técnica abaixo. O exemplo espera uma tabela de artigo com um id em cada linha.
Delete article where id not in (select top 1000 id from article)
Edit: Muito lento para responder minha própria pergunta ...
fonte
Refatorado?
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: tentei os dois no analisador de consultas, a resposta atual é acelerada (maldita ordem por ...)
fonte
A melhor maneira seria inserir as linhas que você deseja em outra tabela, remover a tabela original e então renomear a nova tabela para que tenha o mesmo nome da tabela antiga
fonte
Eu tenho um truque para evitar a execução da
TOP
expressão para cada linha. Podemos combinarTOP
comMAX
para obter oMaxId
que queremos manter. Então nós simplesmente apagar tudo maior do queMaxId
.-- 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: É importante usar
ORDER BY
ao declararMaxId
para garantir que os resultados adequados sejam consultados.fonte