2012-06-19 27 views
13

Tiene una tabla que contiene table1id columna de borrado, es decir int(11), not null, auto_increment y comienza a partir de 1.consulta SQL para obtener registros

Supongamos, que tiene 10.000 registros. Está claro que la identificación del último registro es 10,000. Una vez que eliminó 3 registros, tiene 9.997 registros en la tabla, pero el último valor de identificación de registro sigue siendo 10.000 (si no se eliminó el último registro).

¿Cómo se muestran los registros que se han eliminado utilizando 1 sql consulta?

Gracias.

+2

Cree una tabla con 10,000 valores secuenciales para actuar como una tabla de búsqueda. Luego, seleccione todos los registros de su búsqueda que no existan en su tabla de destino. * (Esto siempre será más rápido que tratar de generar dinámicamente los ID faltantes). * – MatBailie

+0

Si su DMBS tiene una función generate_series() like (no creo que mysql lo tenga), podría usar eso, basado en {min, max }, en lugar de una tabla * de calendario cableado *. – wildplasser

+0

+1 porque aprendí algo nuevo respondiéndola :) Una pregunta decente :) –

Respuesta

5

Creo que lo más fácil sería tener una tabla ficticia/temporal con solo identificadores. 1-1000 luego se unieron a esa mesa.

Pero asegúrese de eliminar los registros "eliminados" de su tabla ficticia/temporal una vez que haya terminado. De lo contrario, aparecerán cada vez.

>> EDITAR < < Puede hacer auto unirse a averiguar si eres identificadores de desaparecidos ....

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

Es fácil, seguro, pero no muy profesional imo :) –

+0

todo lo que realmente necesitas es una tabla de números o una forma de generar números sobre la marcha – dotjoe

+3

@ AndriusNaruševičius No estoy de acuerdo. A veces es profesional tener un método de prueba fallida, no demasiado complicado. – 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); 

Pero lleva mucho tiempo. Tenemos que reducir el tiempo.

2

Utilicé this answer como referencia.

Puede usar la siguiente consulta para encontrar los huecos, que en esencia le darán los "intervalos" de registros eliminados. Por ejemplo, en el siguiente ejemplo, obtiene 2 filas en el resultado final, y los valores son 2 y 3, y 6 y 7. Así que sabe que las filas con ID de 2 a 3 se han eliminado, y las filas con ID de 6 a 7 han sido eliminados (para un total de 4 filas borradas).

Creo que esto cumple con su requisito de obtener el resultado final en "1 consulta SQL", y además, no se utilizan tablas intermedias o ficticias.

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 

Salida:

gap_starts_at gap_ends_at 
2    3 
6    7 
1

Así que, para empezar, voy a mostrar la forma más sencilla de generar 10.000 registros. Sin consultas enormes, sin variables. Tiempo de ejecución: ~ 3ms. LINK

Ahora sobre ese disparador que prometí. LINK

Como puede ver, es muy fácil crear uno. Tenga en cuenta que el desencadenador es mejor no solo porque no necesita varias uniones, sino que también puede almacenar la fecha, la identificación del usuario, etc., etc. (ejemplo muy expansible). Y el punto principal de desencadenar las uniones es: no importa cuántos registros haya/haya/habrá. No necesita ser estricto sobre el tamaño. Es por eso que llamé a la respuesta de sam yi no lo suficientemente profesional. Perdón por malentendido, estoy bastante seguro de que ninguno de nosotros quería insultar a nadie.

Al crear este ejemplo aprendí algunas cosas. Con suerte también lo hizo :)

+0

http://sqlfiddle.com/#!2/ab17a/1 - He creado una alternativa de interfaz de usuario para el comando "delimitador" (tenga en cuenta el "|") debajo del panel de esquema. Al usar esto, puedes construir tu opción basada en disparadores. –

+0

Aah, ya veo, gracias por esto. Otra cosa más que aprendo: P –

+0

Utilizará tu enlace si no te importa :) –

Cuestiones relacionadas