J'ai une table qui peut potentiellement stocker des centaines de milliers d'entiers
desc id_key_table;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id_key | int(16) | NO | PRI | NULL | |
+----------------+--------------+------+-----+---------+-------+
À partir d'un programme, j'ai un grand nombre d'entiers. J'aimerais voir lesquels de ces nombres entiers NE SONT PAS dans la colonne id_key ci-dessus.
Jusqu'à présent, j'ai trouvé les approches suivantes:
1) Itérer sur chaque entier et effectuer:
select count(*) count from id_key_table where id_key = :id_key
Lorsque count est 0, id_key est absent de la table.
Cela semble être une façon horrible et horrible de le faire.
2) Créez une table temporaire, insérez chacune des valeurs dans la table temporaire et effectuez un JOIN sur les deux tables.
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;
Cela semble être la meilleure approche, cependant, je suis sûr qu'il y a une bien meilleure approche à laquelle je n'ai pas encore pensé. Je préférerais ne pas avoir à créer une table temporaire et utiliser une requête pour déterminer les entiers manquants.
Existe-t-il une requête appropriée pour ce type de recherche?
(MySQL)
Réponses:
Votre deuxième solution en utilisant LEFT JOIN est de loin la meilleure approche. Je n'utiliserais pas de table temporaire, j'utiliserais une table régulière et la remplirais avec de nouvelles valeurs chaque fois que vous voudriez exécuter la requête.
la source
Il semble que le "grand ensemble d'entiers" soit encore beaucoup plus petit que le tableau avec "des centaines de milliers d'entiers". Avec cette supposition et à moins qu'il n'y ait un moyen dans MySQL d'utiliser un tableau de vos entiers comme table dans votre instruction SQL, votre deuxième option est probablement la meilleure. Il devrait faire un scan complet de la table temporaire et de l'index sur la table principale. Le principal avantage est qu'il n'a qu'à scanner l'index contenant des centaines de milliers d'entiers une seule fois et n'a qu'à envoyer les résultats au client. Votre requête pourrait (mais ne doit pas être) réécrite comme suit:
la source
Au lieu d'une table temporaire et de l'insertion avec
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
, vous pouvez créer une sous-requête avec toutes les valeurs que vous essayez de vérifier:la source
Comme indiqué dans mon commentaire, cela est probablement plus adapté au stackoverflow. Cependant, je pense que ces deux solutions ne sont pas les meilleures:
La solution 1 nécessite plusieurs appels sélectionnés, très inefficace
La solution 2 est meilleure, mais je ne suis pas sûr que le coût d'insérer autant de valeurs soit la meilleure solution.
Une solution possible 3 serait de faire une seule requête:
et obtenir par programme la différence de votre ensemble d'entiers et de ce qui se trouve dans la base de données. Au pire, (car il y a beaucoup d'entiers) Cette route devrait être meilleure que la solution 1. La solution 2 a le potentiel de retourner également beaucoup d'entiers (si la table a un groupe qui ne se trouve pas dans votre ensemble de données), donc elle dépend ™!
la source
J'ai à peu près abordé cela dans StackOverflow , mais je voudrais en savoir plus sur l'utilisation de la table temporaire permanente (PermTemp). ( température permanente, n'est-ce pas un oxymore ?)
Dans StackOverflow , j'avais la procédure stockée test.CreateSampleTable et test.GetMissingIntegers créer un exemple de table, puis créer une table temporaire dynamique à remplir avant de faire le grand JOIN pour trouver des différences.
Cette fois, créons la table d'exemple avec la table de table permanente.
Voici test.LoadSampleTables:
Après avoir exécuté ceci, voici les tableaux et leur contenu:
Voici les déclencheurs de la table PermTemp
Maintenant, permet d'importer un nouveau lot d'enregistrements, la table test.weekly_batch, certaines clés utilisées auparavant, d'autres clés flambant neuves:
Prenons test.weekly_batch et fusionnons-le en toute sécurité dans test.id_key_table_keys et formons la table test.new_keys_to_load:
Voici le résultat:
À partir de ce moment, utilisez simplement la table new_keys_to_load comme liste des nouvelles clés fessées à importer. Étant donné que new_keys_to_load est plus petit que la table PermTemp, vous devez toujours utiliser new_keys_to_load sur le côté gauche de LEFT JOIN.
la source