Tengo una tabla que potencialmente almacenará cientos de miles de enteros.
desc id_key_table;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id_key | int(16) | NO | PRI | NULL | |
+----------------+--------------+------+-----+---------+-------+
De un programa, tengo un gran conjunto de enteros. Me gustaría ver cuáles de estos enteros NO están en la columna id_key anterior.
Hasta ahora he llegado con los siguientes enfoques:
1) Iterar a través de cada número entero y realizar un:
select count(*) count from id_key_table where id_key = :id_key
Cuando el recuento es 0, falta la tecla id_ de la tabla.
Esto parece una forma horrible, horrible de hacerlo.
2) Cree una tabla temporal, inserte cada uno de los valores en la tabla temporal y realice una UNIÓN en las dos tablas.
create temporary table id_key_table_temp (id_key int(16) primary key );
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
select temp.id_key
from id_key_table_temp temp left join id_key_table as main
on temp.id_key = main.id_key
where main.killID is null;
drop table id_key_table_temp;
Este parece ser el mejor enfoque, sin embargo, estoy seguro de que hay un enfoque mucho mejor en el que aún no he pensado. Prefiero no tener que crear una tabla temporal y usar una consulta para determinar qué enteros faltan.
¿Hay una consulta adecuada para este tipo de búsqueda?
(MySQL)
Respuestas:
Su segunda solución usando el LEFT JOIN es, con mucho, el mejor enfoque. No usaría una tabla temporal, usaría una tabla normal y la llenaría con nuevos valores cada vez que quisiera ejecutar la consulta.
fuente
Parece que el "gran conjunto de enteros" es aún considerablemente más pequeño que la tabla con "cientos de miles de enteros". Con esa suposición y a menos que haya una manera en MySQL de usar una matriz de sus enteros como una tabla en su declaración SQL, su segunda opción es probablemente la mejor. Debe hacer un análisis completo de la tabla temporal y el índice en la tabla principal. El beneficio principal es que solo tiene que escanear el índice que contiene cientos de miles de enteros una vez y solo tiene que enviarle al cliente los resultados. Su consulta podría (pero no necesita ser) reescrita como sigue:
fuente
En lugar de una tabla temporal e insertar con
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
, puede construir una subconsulta con todos los valores que está intentando verificar:fuente
Como se señaló en mi comentario, esto probablemente sea más adecuado para stackoverflow. Sin embargo, creo que ambas soluciones no son las mejores:
La solución 1 requiere múltiples llamadas selectas, muy ineficiente
La solución 2 es mejor, pero no estoy seguro de que el costo de insertar tantos valores sea la mejor solución.
Una posible solución 3 sería hacer una consulta:
y programáticamente obtenga la diferencia de su conjunto de enteros y de lo que hay en el DB En el peor de los casos, (ya que son muchos enteros) Esta ruta debería ser mejor que la Solución 1. La Solución 2 TAMBIÉN tiene el potencial de devolver muchos enteros (si la tabla tiene un montón que no está en su conjunto de datos), entonces depende ™!
fuente
Más o menos abordé esto en StackOverflow , pero me gustaría dar más detalles sobre el uso de la tabla temporal permanente (PermTemp). ( temperatura permanente, ¿no es eso un oxímoron ?)
En StackOverflow , tuve la prueba de procedimiento almacenado. CreateSampleTable y test.GetMissingIntegers hacen una tabla de muestra y luego crean una tabla temporal dinámica para rellenar antes de hacer la gran JOIN para encontrar diferencias.
Esta vez, creemos la tabla de muestra junto con la tabla de tabla permanente.
Aquí está test.LoadSampleTables:
Después de ejecutar esto, aquí están las tablas y sus contenidos:
Aquí están los disparadores para la tabla PermTemp
Ahora, importemos un nuevo lote de registros, tabla test.weekly_batch, algunas claves usadas antes, otras claves completamente nuevas:
Tomemos test.weekly_batch y combinémoslo con seguridad en test.id_key_table_keys y formemos la tabla test.new_keys_to_load:
Aquí está el resultado:
A partir de este punto, simplemente use la tabla new_keys_to_load como la lista de nuevas claves para importar. Como new_keys_to_load es más pequeño que la tabla PermTemp, siempre debe usar new_keys_to_load en el lado izquierdo de LEFT JOIN.
fuente