5. Desmistificando o SELECT no SQL Server: O FROM – 2ª Sub-fase

Post 5/5. Este post é parte da série: Desmitificando o SELECT no SQL Server
Tempo de leitura estimado: 7 minutos

sql=O FROM é a parte de um comando SELECT onde especificamos as tabelas que precisamos para extrair a informação. Assim como podemos efetuar algumas operações com números, é possível efetuar operações entre tabelas. Já vimos uma delas, o CROSS JOIN, que é uma operação para combinar cada linha de uma tabela com cada linha de outra tabela.

O CROSS JOIN é uma operação útil em muitos casos. Porém, creio que a operação mais usada é o famoso “INNER JOIN”. Acredito que a maioria daqueles que estão lendo este post aprenderam que o INNER JOIN serve para “juntar duas tabelas onde duas colunas possuem o mesmo valor”. Essa é uma definição boa e didática, mas a partir de agora esqueça a forma como você conhece um INNER JOIN. A 2ª Sub-fase do processamento lógico do JOIN, que faz parte do processamento lógico do FROM, irá te apresentar um nova forma de ver um INNER JOIN, e vai te permitir ter mais domínio e mais possibilidades de uso do mesmo.

A cláusula ON

Diferentemente do CROSS JOIN, todos os outros operadores de JOIN exigem que uma cláusula seja especificada: o “ON”. Esta cláusula permite que um filtro seja informado (na verdade, um predicado, ja já explico melhor). Este filtro pode ser qualquer expressão válida da linguagem T-SQL que resulte em VERDADEIRO ou FALSO. Isto é, você irá ver que um JOIN não significa juntar linhas onde uma coluna seja igual a outra, e sim, onde o predicado da cláusula ON seja VERDADEIRO!

A 2ª Sub-Fase: Aplicar o filtro da cláusula ON

No post anterior, você viu que o resultado da 1ª sub-fase é uma tabela contendo a combinação de todas linhas entre as duas tabelas envolvidas no operador que está sendo processado. Nós chamamos esse resultado de “VFROM-S1”, que é a tabela resultante da 1ª sub-fase.

Na próxima fase, o SQL Server vai pegar a “VFROM-S1” e adicionar uma nova coluna, que vamos chamar de “ResultadoON”, cujo os valores possíveis são  “VERDADEIRO” ou “FALSO”. Para cada linha de “VFROM-S1”, o SQL Server vai aplicar o filtro da cláusula ON e o resultado será salvo nesta nova coluna. Após avaliar todas as linhas, o SQL Server vai retornar somente as linhas cujo a coluna “ResutaldoON” seja VERDADEIRO. Este será o resultado produzido por esta fase.

Para cada linha da tabela VFROM-S1, o resultado do predicado ON será salvo na coluna ResultadoON. Somente as linhas onde esta coluna for VERDADEIRO serão mantidas

Para cada linha da tabela VFROM-S1, o resultado do predicado ON será salvo na coluna ResultadoON. Somente as linhas onde esta coluna for VERDADEIRO serão mantidas

E é isso o que faz um INNER JOIN. Ele mantém as linhas somente onde a condição do ON é VERDADEIRA. Geralmente, a condição que usamos é “Tabela_Esquerda.Coluna = Tabela_Direita.Coluna”. Mas nada impede que condições mais complexas sejam usadas, usando operadores de comparação mai complexos como um IN, EXISTS, etc.

Para ilustrar melhor o que ocorre nesta fase, vamos realizar um INNER JOIN simples, entre a tabela cliente e pedidos (scripts para criação lá no primeiro post). Vamos trazer todos os clientes e seus respectivos pedidos, segue:

Agora que conhecemos as duas primeiras sub-fases, podemos acompanhar, passo-a-passo como a query acima será processada. Vamos nos preocupar agora somente com o FROM.

Vamos acompanhar sub-fase por sub-fase o que ocorre em uma operação de JOIN simples

Vamos acompanhar sub-fase por sub-fase o que ocorre em uma operação de JOIN simples

Ao executar o FROM nos deparamos com o primeiro operador, um “INNER JOIN”. Sabemos que o “INNER JOIN” faz parte do grupo dos JOINS, então vamos executar as sub-fases do JOIN. A primeira sub-fase, conforme visto neste post, é o produto cartesiano entre as duas tabelas envolvidas. O resultado da primeira sub-fase seria este:

Conforme já mencionei, a primeira fase sempre é executada independentemente do tipo de JOIN

Conforme já mencionei, a primeira fase sempre é executada independentemente do tipo de JOIN

Bom, como a operação atual é um “INNER JOIN” então devemos passar para a próxima fase. Se fosse um “CROSS JOIN” iríamos parar exatamente aqui e esse seria o resultado do seu SELECT. Lembrando que se houverem mais operadores no FROM, este resultado seria o input da esquerda para o próximo operador!

Como estamos processando um INNER JOIN, agora o próximo passo é aplicar o filtro da cláusula ON. Primeiro, de posse da tabela virtual gerada pela 1ª sub-fase, a “VFROM-S1”, devemos adicionar a coluna “ResultadoON”. Para cada linha, o sql server vai avaliar a expressão na cláusula ON e o resultado será salvo nesta coluna, que será VERDADEIRO ou FALSO. A cláusula ON que foi informada na query é “C.clienteID = P.clienteID”. A tabela virtual “VFROM-S1”, iria se parecer com essa:

Na 2ª sub-fase do JOIN, para cada linha da tabela virtual VFROM-S1, vamos AVALIAR a condição da cláusula ON.

Repare nas duas linhas indicadas na imagem. A condição do filtro ON só enxerga os valores das colunas da linha em que está se verificando. Graças a isso, você consegue o efeito “somente linhas onde certas colunas são iguais”.

 

Neste ponto, o SQL Server vai manter somente as linhas onde a coluna “ResultadoON” seja “VERDADEIRO”.

Neste ponto, a coluna "ResultadoON" já possui os valores todos preenchidos. Devemos descartar todas as linhas que forem "FALSO".

Neste ponto, a coluna “ResultadoON” já possui os valores todos preenchidos. Devemos descartar todas as linhas que forem “FALSO”.

 

Em outras palavras, ele irá descatas as linhas onde “ResultadoON = FALSO”.

O resultado da 2ª sub-fase não inclui a coluna "ResultadoON", que é enxergada somente nesta fase.

O resultado da 2ª sub-fase não inclui a coluna “ResultadoON”, que é enxergada somente nesta fase.

 

Ao executar este código, você verá que o resultado produzido foi bem semelhante com essa tabela “VFROM-S2. Se houvesse mais JOINS no FROM, esse resultado iria servir como a tabela da esquerda para o próximo operador. Como em nossa query não há mais para processar no FROM, então este é o resultado do FROM. Fácil né!? Antes de finalizar, algumas observações:

  • Pode parecer absurdo essa lógica em tabelas muito grandes. Com certeza seria um processamento extremamente ineficiente. Porém, conforme eu já mencionei nos posts anteriores, o processamento físico, isto é, o caminho real a ser seguido pelo SQL Server, sofrerá algumas otimizações, mas o resultado produzido  será o mesmo que produzido seguindo o processamento lógico, exatamente o mesmo! Lembre-se: o processamento lógico é como o SQL Server entende o que deve ser feito.
  • A cláusula ON aceita qualquer EXPRESSÃO BOOLEANA VÁLIDA DO T-SQL. Para ser mais correto, o filtro ON pode ser qualquer “PREDICADO” válido. Um predicado é uma expressão que só tem dois resultados: VERDADEIRO ou FALSO (na verdade há um terceiro valor… mas isso é pra depois… :-)). Há vários operadores na linguagem T-SQL para construir desde predicados simples, até o mais complexos. No SQL Server existem somente três lugares em que podemos especificar predicados para filtrar linhas: Na cláusula ON, no WHERE e no HAVING. Isso significa, que todas estas queries são válidas e irão ser executadas sem erros para o SQL Server:
 NOTA: Não vá sair alterando todos as suas queries achando que vai melhorar a performance. Eu disse que todas as queries acima são válidas, não necessariamente são eficientes 🙂 . Por enquanto, estamos falando de processamento lógico, e precisamos primeiro entender o que os operadores fazem e o que eles irão produzir para depois otimizá-los. 

Agora você já sabe que o INNER JOIN não serve apenas para juntar linhas baseada na igualdade entre duas colunas. Usando a sua criatividade e juízo, você poderá começar a enxergar mais utilidades e aplicações do CROSS JOIN e INNER JOIN. O próximo post será sobre a 3ª sub-fase do JOIN e creio que muita coisas sobre LEFT JOINS e RIGHT JOINS serão desmitificadas e você irá dominar esses operadores.

Ah, apenas para reforçar, deixo claro que esta série é baseada no conteúdo do livro Inside SQL Server 2008: T-SQL Querying. Recomendo muuuuuuuuuuuuuuuuuuuuuuuuuuuito a leitura!

DESAFIO

Bom, será que você já desmistificou o INNER JOIN mesmo? Ou ainda treme igual uma mocinha indefesa só de pensar em usá-lo? Vejamos… Considere esta query que acabamos de usar:

Você já sabe o que ela faz: combina (junta, relaciona, gruda, como preferir) as linhas de Cliente e Pedido onde as colunas clienteID de Cliente e clienteID de Pedido possuem o mesmo valor. Inverta o filtro de igualdade para o filtro de desigualdade (“!=”):
E você irá fazer o contrário: trazer todos os pedidos que não pertencem aos clientes. Ora, o pedido de ID = 7 não pertence a nenhum cliente (cliente = NULL) e não foi retornado para nenhuma linha da tabela Cliente. NULL é diferente de qualquer coisa, certo? Realize um CROSS JOIN entre estas duas tabelas e você verá que o pedido de ID = 7 irá aparecer para cada cliente. Perguntas:

  • As linhas de Pedido, onde pedidoID = 7, foram removidas na primeira ou segunda fase do JOIN? Qual foi o motivo de terem sido removidas do resultado?
  • Se NULL é diferente de qualquer coisa, porque essa linha não foi retornada para cada cliente?

Os scripts para a criação das tabelas acima estão neste post. Utilize os comentários para deixar sua reposta! Até a próxima!

Navegue na série<< 4. Desmistificando o SELECT no SQL Server: O FROM – 1ª Sub-Fase

Leave a reply

Your email address will not be published.