Prenant les deux variables de table suivantes, existe-t-il une alternative (plus rapide / plus courte / plus efficace) pour supprimer datatables de @tbl_big
qui n'existent pas dans @tbl_small
? La raison en est que j'ai un grand choix de données, et en fonction des parameters optionnels (dans une procédure), je filter datatables plus avant avant de les présenter à l'user.
La colonne userId
est indexée dans la table physique à partir de laquelle les colonnes de variable de table sont renseignées.
DECLARE @tbl_big TABLE (userID int); INSERT INTO @tbl_big (userID) VALUES (1),(5),(10),(20),(30),(40),(60),(100); DECLARE @tbl_small TABLE (userID int); INSERT INTO @tbl_small (userID) VALUES (1),(5),(10),(20) -- this deletes 30,40,60,100 from @tbl_big DELETE FROM @tbl_big WHERE (userID NOT IN (SELECT userID FROM @tbl_small)); SELECT * from @tbl_big;
http://www.sqlfiddle.com/#!6/d41d8/12674
Je me suis demandé si INTERSECT
ou EXCEPT
pourrait le faire mais ne peut pas les comprendre.
Mise à jour: les résultats INTERSECT
/ INTERSECT
inclus comme réponse. Je ne suis pas sûr que le encoding soit plus court …?
Typiquement, existe ou joint externe gauche ferait l'affaire.
DELETE b FROM @tbl_big b WHERE NOT EXISTS ( SELECT 1 FROM @tbl_small s WHERE s.userID = b.userID);
OU
DELETE b FROM @tbl_big b LEFT OUTER JOIN @tbl_small s ON s.userID = b.userID WHERE s.userID IS NULL;
Eh bien, c'est moderne 🙂 mais je ne suis pas sûr que ce soit plus rapide qu'une suppression où n'existe pas:
DECLARE @tbl_big TABLE (userID int) DECLARE @tbl_small TABLE (userID int) INSERT INTO @tbl_big (userID) VALUES (1),(5),(10),(20),(30),(40),(60),(100) INSERT INTO @tbl_small (userID) VALUES (1),(5),(10),(20) ;with deleting as ( SELECT * from @tbl_big except select * from @tbl_small) DELETE b FROM @tbl_big b where exists ( select * from deleting c where c.userID = b.userID) SELECT * from @tbl_big
DECLARE @tbl_big TABLE (userID int) DECLARE @tbl_small TABLE (userID int) DECLARE @tbl_new TABLE (userID int) INSERT INTO @tbl_big (userID) VALUES (1),(5),(10),(20),(30),(40),(60),(100) INSERT INTO @tbl_small (userID) VALUES (1),(5),(10),(20) INSERT INTO @tbl_new SELECT userID FROM @tbl_big INTERSECT SELECT userID FROM @tbl_small; SELECT * from @tbl_new;
J'ai finalement pensé EXCEPT
, mais ce n'est pas vraiment plus facile à lire!
DELETE b FROM @tbl_big b INNER JOIN ( SELECT * FROM @tbl_big EXCEPT SELECT userID FROM @tbl_small) s ON s.userID = b.userID;
Je me rends count maintenant INTERSECT
supprimerait la mauvaise moitié des données (par exemple datatables NOT IN @tbl_small
)