SELECT U.*
FROM Units U
WHERE NOT EXISTS (
SELECT 1
FROM People P
WHERE U.ID = P.UnitID
)
Veuillez noter que cela s'appelle un (anti) semi-jointure. C'est une jointure réelle et n'est pas une sous-requête corrélée.
Une autre méthode couramment utilisée est:
SELECT U.*
FROM
Units U
LEFT JOIN People P ON U.ID = P.UnitID
WHERE
P.UnitID IS NULL
Notez que des critères supplémentaires sur la jointure (dites que vous vouliez rejoindre uniquement aux personnes qui ont été actifs) doivent être dans la clause de jointure. Cela ne marchera pas pour dire WHERE P.UnitID IS NULL AND P.Active = 1
. Dans mon expérience, chacune des différentes requêtes peut s'avérer être le gagnant de la performance en fonction du plan d'exécution réel choisi. La façon dont le moteur utilise les statistiques pour prédire le nombre de lignes peut lui faire choisir des plans d'exécution sous-optimaux pour certaines requêtes, même lorsque les statistiques sont correctement mises à jour. Remarque: l'utilisation de "SELECT 1" dans vos semi-jointures au lieu de "SELECT *" permet d'économiser des cycles lors de la compilation des requêtes, puisque le * est en fait étendu à la liste des colonnes, puis supprimé ultérieurement.
Je ne sais pas pourquoi quelqu'un a voté pour cette question. C'est une question légitime, rédigée de façon claire et concise. –
@araqnid, tsql n'est pas la même chose que sql. Il y a de légères différences, et je crois que la fonction de jointure en fait partie. – Malfist
mais je n'en suis pas sûr – Malfist