Treinamento para Consultas com SQL Server – Parte 2 - JOINS - Outros tipos de joins

No post anterior faltou acrescentar alguns detalhes sobre LEFT JOINS que coloco agora.
Use LEFT JOIN quando:
  • O objetivo for listar todos os registros de uma tabela e mostrar colunas de outra havendo ou não correspondências.
  • Precisar saber se existem registros filhes de uma tabela pai em uma (ou várias) filho.
Não use para fazer filtros, conforme foi demonstrado com INNER JOIN.

A maneira de restringir (condições de busca) também é semelhante ao INNER JOIN.

Uma questão sobre desempenho

O desempenho com LEFT JOIN é melhor do que com INNER JOIN, porém, pode ser que em alguns casos seja necessário usar mesmo o INNER.

Usando CROSS JOIN (na verdade é melhor nem usar)

Este tipo de JOIN está aqui meramente para exemplo pois causa muitos problemas. Consiste em vez de usar o termo JOIN, colocar as tabelas relacionadas na cláusula FROM.

SELECT [TABELA1.COLUNAS] ...
   ,[TABELA2.COLUNAS...]
   , ...
   ,[TABELAn.COLUNAS...]
FROM [TABELA1], [TABELA2], ..., [TABELAn]

O problema aqui é que este tipo de JOIN traz como resultado, caso nenhum filtro seja especificado na cláusula WHERE, o produto cartesiano dos registros de todas as tabelas, ou seja para cada registro na TABELA1, todos os registros da TABELA2 até a “TABELAn” são trazidos.

Se fizermos o primeiro exemplo de INNER JOIN deste jeito onde PERSON.PERSON tem 19.972 registros e HUMANRESOURCES.EMPLOYEE. 290, o número de registros recuperados será 19.972 x 290 = 5.791.880. A consulta (execute por sua conta e risco...) fica assim:

select p.FirstName + ' ' + p.LastName as CompleteName
   ,hre.JobTitle
   ,hre.BirthDate
from person.person p, HumanResources.Employee hre


Uma forma de se evitar o produto cartesiano é através da cláusula WHERE:

select p.FirstName + ' ' + p.LastName as CompleteName
   ,hre.JobTitle
   ,hre.BirthDate
from person.person p, HumanResources.Employee hre
where p.BusinessEntityID=hre.BusinessEntityID

O que nesse caso, vai ser equivalente à consulta com INNER JOIN.

Se uma terceira tabela for incluída, digamos, com cem registros, a conta ficará 19.972 x 290 x 100 = 579.188.000, logo, dá para perceber o tamanho do estrago e a dica aqui é NÃO USE ISSO DE JEITO NENHUM. A possibilidade de estragos e problemas com desempenho é muito grande.

SELF JOIN e algo um pouco esquisito - recursão

Como o próprio nome diz, consiste em fazer referência a própria tabela. O que pode parecer muito esquisito inicialmente, mas, tem sua aplicação principalmente para armazenamento e representação de dados hierárquicos, como, por exemplo:
  • Árvore de pastas e subpastas
  • Funcionário e seu encarregado – que na prática é também um funcionário
  • Departamento e departamentos afiliados
Com este tipo de recurso você não precisa ter uma tabela para cada nível, basta apenas ter um campo indicando a chave primária para o registro pai. Vamos considerar o exemplo de árvore de pastas considerando a seguinte tabela:



Nesta tabela temos três colunas:
  1. FolderId: chave primária para cada pasta
  2. ParentFolderId: chave estrangeira e Id da pasta que está um nível acima, ou, pasta “pai”, se preferir.
  3. Name: nome da pasta
Note que há um relacionamento circular representado no diagrama. Este relacionamento é a chave estrangeira que liga a coluna ParentFolderId com a coluna FolderId. Com isso é possível listar as pastas tendo o nome da pasta atual e a sua pasta pai usando a seguinte consulta, que faz uso do SELF JOIN:

select df0.Name as ParantFolder
   ,df1.Name as FolderName
from documents.folders as df1
left join documents.folders as df0 on
    df0.FolderId=df1.ParentFolderId;

Não existe um limite de quantas auto referências podem ser feitas, deve-se apenas, prestar atenção para não criar consultas recursivas e deixar o banco em loop causando um lock desnecessário.

 
O SQL server tem um tipo de coluna – HIERARCHID – próprio para armazenar dados do tipo como vimos acima (hierárquicos), embora, a maneira mais direta se se fazer isto seja como vimos no exemplo.

Terminamos por aqui a segunda parte da série de treinamentos em SQL referente às JOINS. A próxima etapa será falar sobre os filtros e a cláusula WHERE. Até lá.