2012-06-19 12 views
13

Hai una tabella che contiene table1id colonna, che è int(11), not null, auto_increment e parte da 1.query SQL per ottenere il record eliminati

Supponiamo, si dispone di 10.000 record. È chiaro che l'ID dell'ultimo record è 10.000. Dopo aver rimosso 3 record, nella tabella sono presenti 9.997 record, ma l'ultimo valore ID record è ancora 10.000 (se l'ultimo record non è stato eliminato).

Come visualizzare quali record sono stati rimossi utilizzando 1 query SQL?

Grazie.

+2

Creare una tabella con 10.000 valori sequenziali per fungere da tabella di ricerca. Quindi seleziona tutti i record dalla tua ricerca che non esistono nella tabella di destinazione. * (Questo sarà sempre più veloce di provare a generare dinamicamente gli ID mancanti.) * – MatBailie

+0

Se il tuo DMBS ha una funzione come generate_series() (non penso che mysql lo abbia) potresti usarlo, basato su {min, max }, invece di una tabella * di calander * cablata. – wildplasser

+0

+1 perché ho imparato qualcosa di nuovo rispondendo :) Una domanda decente :) –

risposta

5

Penso che sarebbe più facile avere una tabella fittizio/temp con solo id. 1-1000 poi a sinistra si uniscono a quel tavolo.

Ma assicuratevi di rimuovere i record "cancellati" dalla vostra tabella dummy/temp una volta che avete finito. Altrimenti, si presenteranno ogni volta.

>> EDIT < < Si può fare auto iscriverti per capire se sei ids mancanti ....

select a.id + 1 MissingIds 
from <table> a 
left join <table> b 
    on a.id = b.id - 1 
where b.id is null 
    and a.id < 10000 
+3

È facile, certo, ma non molto proffessional imo :) –

+0

tutto ciò di cui hai veramente bisogno è una tabella di numeri o un modo per generare numeri al volo – dotjoe

+3

@ AndriusNaruševičius Non sono d'accordo. A volte è professionale avere un metodo di prova fallito, non un metodo complicato. – fancyPants

1
DECLARE @myTestTable1 TABLE 
(
id INT IDENTITY(1,1) NOT NULL 
,testVal int 
) 

DECLARE @increment AS int = 1 

WHILE (@increment <= 10000) 
BEGIN 
INSERT INTO @myTestTable1 
VALUES (@increment) 

SET @increment += 1 
END 

DELETE FROM @myTestTable1 WHERE id IN (100,200,300) 

--SELECT * FROM @myTestTable1 

;WITH Missing (missnum, maxid) 
AS 
(
    SELECT 1 AS missnum, (select max(id) from @myTestTable1) 
    UNION ALL 
    SELECT missnum + 1, maxid FROM Missing 
    WHERE missnum < maxid 
    ) 
    SELECT missnum 
    FROM Missing 
    LEFT OUTER JOIN @myTestTable1 tt on tt.id = Missing.missnum 
    WHERE tt.id is NULL 
    OPTION (MAXRECURSION 0); 

Ma ci vuole molto tempo. Dobbiamo ridurre il tempo.

2

Ho usato this answer come riferimento.

È possibile utilizzare la query seguente per trovare gli spazi vuoti, che in sostanza forniranno il record "intervalli" cancellati. Ad esempio, nell'esempio seguente, ottieni 2 righe nel risultato finale e i valori sono 2 e 3, e 6 e 7. Quindi sai che le righe con ID da 2 a 3 sono state eliminate e le righe con ID da 6 a 7 sono stati cancellati (per un totale di 4 righe cancellate).

Credo che questo soddisfi le vostre esigenze di ottenere il risultato finale in "1 query SQL", e in più, non vengono utilizzate tabelle intermedie o fittizie.

delimiter $$ 
use test 
$$ 

create table mytable (id int not null auto_increment, name varchar(100), primary key (id)); 
$$ 

insert into mytable (name) values('a')$$ 
insert into mytable (name) values('b')$$ 
insert into mytable (name) values('c')$$ 
insert into mytable (name) values('d')$$ 
insert into mytable (name) values('e')$$ 
insert into mytable (name) values('f')$$ 
insert into mytable (name) values('g')$$ 
insert into mytable (name) values('h')$$ 


delete from mytable where id = 2$$ 
delete from mytable where id = 3$$ 
delete from mytable where id = 6$$ 
delete from mytable where id = 7$$ 


SELECT (t1.id + 1) as gap_starts_at 
    , (SELECT MIN(t3.id) -1 
      FROM mytable t3 
     WHERE t3.id > t1.id) as gap_ends_at 
    FROM mytable t1 
WHERE NOT EXISTS (SELECT t2.id FROM mytable t2 WHERE t2.id = t1.id + 1) 
HAVING gap_ends_at IS NOT NULL 

uscita:

gap_starts_at gap_ends_at 
2    3 
6    7 
1

Quindi, per cominciare, ho intenzione di mostrare il modo più semplice per generare 10.000 record. Nessuna query di enorme successo, nessuna variabile. Tempo di esecuzione: ~ 3ms. LINK

Ora su quel grilletto che ho promesso. LINK

Come potete vedere, è davvero facile crearne uno. Tieni presente che il trigger è migliore non solo per non aver bisogno di vari join, ma puoi anche memorizzare la data, l'id utente, ecc. Ecc. (Esempio molto espandibile). E il punto principale del trigger su join è: non ti importa quanti record ci sono/sono/saranno. Non è necessario essere rigidi riguardo alle dimensioni. Ecco perché ho chiamato la risposta di sam yi non abbastanza professionale. Scusa per l'incomprensione, sono abbastanza sicuro che nessuno di noi volesse insultare nessuno.

Creando questo esempio ho imparato alcune cose. Spero di averlo fatto anche tu :)

+0

http://sqlfiddle.com/#!2/ab17a/1 - Ho creato un'interfaccia utente alternativa al comando "delimitatore" (nota il "|") sotto il pannello dello schema. Usando questo, puoi costruire la tua opzione basata sul trigger. –

+0

Aah, vedo, grazie per questo. Un'altra cosa che imparo: P –

+0

Userò il tuo link se non ti dispiace :) –