web-dev-qa-db-fra.com

Comment vérifier si tous les éléments d'un tableau existent dans une table?

Prenons un tableau d'identifiants de taille n au niveau de l'application. par exemple [132,3425,13,13, ... 392] où n est supérieur à 100k entrées. Certaines de ces entrées sont répétées.

Je dois vérifier si tous ces registres sont contenus dans une table MySQL contenant plus de 5 millions d'entrées.

Maintenant, je vérifie l'un après l'autre, mais ce processus prend beaucoup de temps.

Comment puis-je faire cette vérification en un seul chèque, ou peut-être rendre cela plus efficace.

Je voudrais savoir s'ils existent tous sur la table et, si possible, savoir ceux qui n'existent pas déjà sur cette table.

1
Daniel Santos

Comptez d'abord le nombre de nombres distincts. Vous l'avez appelé n. alors

SELECT COUNT(*) FROM tbl
    WHERE id IN (very-long-list)

Vérifiez si cela renvoie n.

Si, au lieu de cela, vous avez mis ces chiffres dans un autre tableau, cela peut être optimal:

Table `nums` contains the `n` values.
ALTER TABLE tbl ADD INDEX(id);  -- if it does not already exist.
SELECT ! EXISTS ( SELECT * FROM nums LEFT JOIN tbl USING(id)
                      WHERE tbl.id IS NULL )

Cela vérifiera chaque nums.id pour voir s'il se trouve dans votre tbl. Plus important encore, il s'arrête lorsque le premier élément manquant est trouvé. La sortie est 1 ou 0.

1
Rick James

Je recommande d'utiliser le code d'application pour insérer le tableau dans une table temporaire, y compris un champ d'identité afin que vous puissiez stocker chaque enregistrement, même s'il est répété. (la syntaxe est la même que CREATE TABLE mais en utilisant CREATE TEMPORARY TABLE):

CREATE TEMPORARY TABLE A (
     id BIGINT NOT NULL AUTO_INCREMENT,
     number BIGINT NOT NULL,
     PRIMARY KEY (id)
);

Faites ensuite une requête pour vérifier/déterminer si le nombre existe dans la grande table. Quelque chose comme ça:

--supose la table temporaire est A et la grande table est B et les champs que vous comparez sont appelés NUMBER.

SELECT A.id, A.number as ARRAY_NUMBER,
CASE
    WHEN B.number IS NULL THEN 'not found'
    ELSE 'found'
END as FOUND_IN_TABLE
FROM A LETF OUTER JOIN B ON A.number = B.number

bonne chance!

3
AMG
CREATE TEMPORARY TABLE B_Temp (
     id BIGINT NOT NULL
     PRIMARY KEY (id)
     INDEX unid (id)
);

Je chargerais une table temporaire comme dans la réponse de @AMG. Mais ma requête ressemblerait à ceci:

select id
from a
where not exists (
select *
from B_Temp
where a.id = b.id
)

Vous souhaitez désactiver l'index sur la colonne id avant de charger les données et le réactiver après pour que cela fonctionne correctement. Si vous faites cela régulièrement, vous pourriez envisager d'en faire une table permanente.

3
David Buttrick