Comment remplacer cette clause where par une jointure?

8

Typiquement, quand je vois du SQL qui utilise quelque chose comme:

select * from employees where epmloyeeTypeId in (select id from type where name = 'emp') 

Je remplace le wherepar ceci:

select e.* from employees e 
inner join type t on t.id=e.epmloyeeTypeId and t.name = 'emp'

Est-il possible de faire la même chose avec l'inverse au cas où c'est un not in(comme ci-dessous) au lieu d'une inclause?

INSERT into Subscriptions(ProjectId, RecordTypeCID, NTID, Active, Added, LastUpdate, UpdateBy)   
 SELECT @ProjectId, RecordTypeCID, @NTID, 1, GETDATE(), GETDATE(), @NTID  
 FROM @Check CHK  
 WHERE CHK.ActiveStatus=1  
        And Not Exists (SELECT SubscriptionId FROM Subscriptions  
                        WHERE ProjectId=@ProjectId           
                        and NTID=@NTID          
                        and RecordTypeCID = CHK.RecordTypeCID
                        )  

Considérations supplémentaires

Puis-je faire ceci:

INSERT INTO Subscriptions(ProjectId, RecordTypeCID, NTID,Active, Added, LastUpdate, UpdateBy)   
SELECT @ProjectId, RecordTypeCID, @NTID,1, GETDATE(), GETDATE(), @NTID  
FROM @Check CHK
    LEFT JOIN Subscriptions subs ON subs.RecordTypeCID = CHK.RecordTypeCID
        AND NTID = @NTID
        AND ProjectId = @ProjectId

        AND CHK.ActiveStatus = 1
        AND subs.SubscriptionId IS NULL
kacalapy
la source

Réponses:

6

Oui. Vous pouvez remplacer par une touche LEFT JOIN ... WHERE IS NULL. Fonctionne beaucoup plus rapidement.

INSERT INTO Subscriptions(
    ProjectId, RecordTypeCID, NTID,
    Active, Added, LastUpdate, UpdateBy)   
SELECT @ProjectId, RecordTypeCID, @NTID,
    1, GETDATE(), GETDATE(), @NTID  
FROM @Check CHK
LEFT JOIN Subscriptions subs
    ON subs.RecordTypeCID = CHK.RecordTypeCID
        AND NTID = @NTID
        AND ProjectId = @ProjectId
WHERE CHK.ActiveStatus = 1
    AND subs.SubscriptionId IS NULL
Eric Humphrey - lotsahelp
la source
quelle est la performance différente entre les deux? Je pense que les jointures sont bien plus rapides que l'utilisation dans (...) ou pas dans (...), vous n'avez jamais pensé qu'il existe (...) une idée?
kacalapy
puis-je également inclure tout dans la jointure, voir ma modification au bas de la question
kacalapy
1
Vous devez avoir la clause WHERE comme je l'ai dit.
Eric Humphrey - lotsahelp
4
"Effectue beaucoup plus vite"? Que PAS EXISTE ou PAS DANS? Si ce n'est pas le cas, oui. Si ce n'est PAS EXISTANT, assez égal.
gbn
1
Exemple ou SO
gbn
7

Votre NOT EXISTS est plus efficace dans la plupart des cas.

LEFT JOIN fait correspondre en interne toutes les lignes, puis filtre sur IS NULL. PAS EXISTE non. Cette multiplication de lignes se produit également dans tout le code basé sur JOIN, vous aurez donc peut-être besoin d'un agrégat supplémentaire (DISTINCT) pour corriger la sortie

NOT IN est généralement faux car les valeurs NULL ne provoquent aucune correspondance.

Vous pouvez également utiliser EXCEPT qui donne le même plan que NOT EXISTS.

SELECT @ProjectId, RecordTypeCID, @NTID,1, GETDATE(), GETDATE(), @NTID  
FROM @Check CHK
EXCEPT
SELECT @ProjectId, RecordTypeCID, @NTID,1, GETDATE(), GETDATE(), @NTID  
FROM Subscriptions
WHERE ProjectId=@ProjectId           
and NTID=@NTID          

Pour info, selon la norme SQL-92 (page 191, cas 3a), le bit SELECT des EXISTS est ignoré.

gbn
la source