SQL - Joins

Pré-requisito : O que é cardinalidade entre 2 tabelas ?

Cardinalidade é quantos registros de uma tabela B existem para cada registro na tabela A. Um exemplo, tabela de clientes. Você só irá cadastrar os clientes uma vez porque senão será uma confusão na sua empresa para saber se o cliente é o JOSEA ou o JOSEB. Isso seria quebrar uma das regras fundamentais em banco de dados ( veja o conceito ACID (Atomic (unico), Consistent(confiável), Isolation(Isolação), Durability(pra sempre)) que diz que cada informação sobre uma entidade deve ser única.

Então pelo certo você cadastraria apenas uma vez um cliente em seu banco de dados. Certo. Mas e se ao invés de clientes forem funcionários e você quisesse cadastrar os filhos do funcionário? Um funcionário pode não ter filhos, pode ter um ou mais filhos ou dependentes, e como você faria? Lógico, você criaria uma tabela de filhos ou dependentes e amarraria a tabela de filhos/dependentes com um campo da tabela de funcionário de maneira que sempre será possível saber a quem pertence os filhos ou dependentes cadastrados.

Sendo assim dizemos que a tabela clientes/funcionários teria uma cardinalidade de 1 para N com a tabela de filhos ou dependentes, pois um pai(1) pode ter vários filhos ou dependentes(N).

E se você fosse cadastrar as esposas dos funcionários ? Você criaria uma tabela a parte ou criaria um campo extra na tabela de funcionários para cadastrar os dados da esposa ? A resposta certa não é única. Se for no Brasil e na maioria dos paises ocidentais você poderia colocar o nome da esposa ou conjuge junto com o cadastro do funcionário porque só é legalmente permitido ter uma esposa nesses paises. Aqui a cardinalidade seria de 1 para 1, ou seja, um marido para uma esposa.

Mas e se fosse um país árabe ou oriental, como Arábia e muitos paises muçulmanos. Lá você pode ter quantas esposas que quiser desde que tenha condições de sustentá-las. Sendo assim nesses países que admitem o casamento com diversas esposas ( não exigem fidelidade conjugal) o correto seria criar uma tabela onde você poderia cadastrar quantas esposas o funcionário tivesse. Neste caso a relação entre marido (1) e esposas(N) seria de 1 para N.


O que é um Join ?

O Join de tabelas nos servidores sql visa obter informações de diversas tabelas numa única pesquisa.

Se você conhece sql sabe que cada entidade do mundo real deve ter sua represetação no banco de dados. Simplificando a explicação, se você tem uma tabela de clientes nela você só deve ter informações dos clientes. Se você tiver que trabalhar com as vendas feitas a esse cliente você criará uma tabela vendas e associará a tabela de clientes e vendas colocando um id (identificação-número-Normalmente um primary-key(PK)) na tabela de clientes e na tabela de vendas você só colocará no campo cliente o número dessa chave.

Portanto se você quiser obter as informações de cliente é só acessar a tabela de clientes.
Se precisar de dados da venda é só acessar a tabela de vendas.
Mas e se eu quiser saber todas as vendas feitas para um cliente ?

Como cliente e vendas são tabelas separadas para obter as informações das duas tabelas ao mesmo tempo faremos um join, uma mesclagem dos dados das duas tabelas.

Esse join (mesclagem) pode ser feito de diversas maneiras dependendo de como queremos que o resultado seja elaborado. Podemos trazer só o que tem em comum nas duas tabelas, tudo o que tem numa mais o que existir na segunda, tudo da segunda tabela mais o que existir na primeira tabela ou tudo da primeira e tudo da segunda 'aglutinando' no mesmo 'registro' as informações comum as duas. O conceito é complicado e explico mais detalhadamente logo abaixo.

Join tipo INNER JOIN

Inner join é a opção que traz os registros das tabelas somente se existir o dado que as case em ambas as tabelas .

Portanto se você der um comando:
Select * from tabA inner Join tabB where tabA.Col1 = tabB.col2
só será retornado os registros com todos os campos da tabA e da tabB onde o campo Col1 for igual ao tabB.col2.
Se não for, nada da tabA será retornado.

Um detalhe avançado sobre a cardinalidade entre as tabelas. Na pesquisa o sql pega um registro da tabA e vai procurar na tabB. E se ele encontrar vários ? (cardinalidade 1 para n) ? Ele vai multiplicar esse 1 registro pelos n que encontrou na tabB. Portanto se ele achar 3 registros na tabB onde a col2 seja igual a tabA.Col1 ele irá retornar 3 registros iguais da tabA e os campos vindos da tabB serão diferntes.

Por isso, se a cardinalidade for de 1 para um um inner join irá trazer o mesmo número de registros que os campos usados como chave de pesquisa existirem. Contudo se a cardinalidade for de um para n irá retornar bem mais dados, os dados da tabA serão multiplicados pelo número de registros coincidentes da tabB.


Join tipo LEFT JOIN

Por exemplo, ao fazer a pesquisa:
select * from tabA left join tabB where tabA.Col1 = tabB.Col2
Como resultado todos os registros da tabA serão retornados, impreterivelmente. Se a chave de pesquisa coincidir ( tabA.Col1 = tabB.Col2 ) os campos da tabB virão preenchidos, senão virão como null ( não encontrados ).

Novamente a cardinalidade definirá o número de registros retornados. Se não existir nada coincidente na tabB os campos da tabA virão todos mas os campos da tabB não virão, terão o valor null. Se existirem vários registros na tabB para cada registro da tabA, o número de registros será multiplicado pela cardinalidade entre as duas tabelas.


Join tipo RIGHT JOIN

Por exemplo, ao fazer a pesquisa:
select * from tabA right join tabB where tabA.Col1 = tabB.Col2
Como resultado todos os registros da tabB serão retornados, impreterivelmente. Se a chave de pesquisa coincidir ( tabA.Col1 = tabB.Col2 ) os campos da tabA virão preenchidos, senão virão como null ( não encontrados ). Exatamente como no left join. Também a Cardinalidade segue a mesma lógica que o left join.


Join tipo OUTER JOIN

Outer Join faria com que a pesquisa:
select * from tabA outer join tabB where tabA.Col1 = tabB.Col2
Voltasse com todos os registros de tabA. Se ouver correspondência com os registros da tabB ( tabA.Col1 = tabB.Col2 ) os campos da tabB virão preenchidos também. Se não houver, os campos da TabA virão preenchidos mas os da tabB virão com null. E se houver algum registro da tabB que não tenha nenhuma correspondência com a tabA será gerados os registros com os campos da tabA com null e os dados da tabB preenchidos.