Há uns dias coloquei aqui um post sobre eliminação de joins e, sem querer, deparei-me hoje com uma situação onde parecia que o SQL Server não estava a fazer um bom trabalho.
Vai-se a ver… e quem não estava a fazer um bom trabalho éramos nós.
A situação era bem mais complicada do que esta, mas se pegarmos no código do último post é rápida de explicar.
Vamos lá de novo.
create table JoinEliminationDemo01 ( id int identity primary key , Col1 uniqueidentifier ) go insert into JoinEliminationDemo01 (Col1) select NEWID() go 10 create table JoinEliminationDemo02 ( id int identity primary key , id_ref int not null , Col1 uniqueidentifier ) go insert into JoinEliminationDemo02 (id_ref, Col1) select (ABS(CHECKSUM(NEWID()))%10)+1, NEWID() from sys.objects a cross join sys.objects b go ALTER TABLE JoinEliminationDemo02 ADD CONSTRAINT JoinEliminationDemo02__id_ref__id FOREIGN KEY(id_ref) REFERENCES JoinEliminationDemo01 (id)
Imaginemos que neste caso queremos a Col1 da JoinEliminationDemo02 e do id da JoinEliminationDemo01.
É muito simples fazer este erro em queries mais complexas com uma mão-cheia de joins.
set statistics time, io on select a.Col1 , b.id from JoinEliminationDemo02 a inner join JoinEliminationDemo01 b on b.id = a.id_ref


Neste exemplo simples percebemos que a nossa execução está a tocar nas duas tabelas quando temos criada uma relação para evitar isso mesmo.
Facilmente chegamos à solução.
Estamos a retirar valores de uma e de outra tabela e, nestes casos, o SQL Server não consegue eliminar a referência.
Se formos buscar o valor que precisamos à JoinEliminationDemo02 o join deverá ser eliminado.
select a.Col1 , a.id_ref from JoinEliminationDemo02 a inner join JoinEliminationDemo01 b on b.id = a.id_ref


Parece óbvio, mas nem sempre é.