Como substituo esta cláusula where por uma junção?

8

Normalmente, quando vejo o SQL que usa algo como:

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

Eu substituo o wherepor este:

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

É possível fazer o mesmo com o inverso, caso seja uma not in(como abaixo) em vez de uma incláusula?

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
                        )  

Considerações adicionais

Posso fazer isso:

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
fonte

Respostas:

6

Sim. Você pode substituir por uma tecla LEFT JOIN ... WHERE IS NULL. Executa muito mais rápido.

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 - lotes de ajuda
fonte
qual o desempenho diferente entre os dois? Eu acho que as junções são muito mais rápidas do que usar em (...) ou não em (...), nunca pensei em existir (...) alguma idéia?
22411 kacalapy
Também posso incluir tudo na junção, ver a minha edição na parte inferior da questão
kacalapy
11
Você precisa ter a cláusula WHERE como afirmei.
Eric Humphrey - lotsahelp
4
"Executa muito mais rápido"? Do que NÃO EXISTE ou NÃO ESTÁ? Se NÃO estiver, sim. Se NÃO EXISTE, é praticamente igual.
gbn 14/02
11
Exemplo ou SO
gbn 14/02
7

Seu NOT EXISTS é mais eficiente na maioria dos casos.

LEFT JOIN combina internamente todas as linhas e depois filtra para IS NULL. NÃO EXISTE não. Essa multiplicação de linhas também acontece em todo o código baseado em JOIN, portanto, você pode precisar de um agregado extra (DISTINCT) para corrigir a saída

NOT IN geralmente está errado porque NULLs não causam nenhuma correspondência.

Você também pode usar EXCEPT, que fornece o mesmo plano 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          

Para sua informação, de acordo com o padrão SQL-92 (página 191, Caso 3a), o bit SELECT dos EXISTS é ignorado.

gbn
fonte