Bom dia pessoal, estou trazendo algumas dicas sobre os joins.

Joins são a maneira de se ligar as tabelas em uma instrução SQL. Nos exemplos, vou me referir a utilização de joins em instruções SELECT, mas a partir do SQL Server 2000 podemos utilizar os joins tanto nas instruções SELECT como UPDATE e DELETE.

Para os exemplos seguintes, criei três tabelas, chamadas PEDIDO, CLIENTE e ITENSPEDIDO, que reproduzem o clássico relacionamento pai-filho:

CREATE TABLE PEDIDO
(
PED_COD INT NOT NULL,
PED_DATA SMALLDATETIME NOT NULL ,
PED_CLI INT NOT NULL
)
CREATE TABLE CLIENTE
(
CLI_COD INT NOT NULL,
CLI_NOME VARCHAR(50) NOT NULL
)
CREATE TABLE ITENSPEDIDO
(
PED_COD INT NOT NULL,
ITEN_COD INT NOT NULL,
ITEN_QTD NUMERIC(5,2) NOT NULL
)

A tabela PEDIDO possui uma relação de um-para-muitos com a tabela ITENSPEDIDO, através do campo PED_COD. A tabela PEDIDO possui uma relação de um-para-um com a tabela CLIENTE, através do campo CLI_COD.

Percebam que neste exemplo não estou utilizando contraints declarativas de integridade referencial (DRI) como chaves primárias ou chaves estrangeiras, pois quis montar um exemplo simples. Também não me preocupei com cardinalidade da relação e normalização do modelo.

Antes de continuar, aconselho ao leitor incluir alguns registros nestas tabelas para tornar os exemplos a seguir mais compreensíveis.

Agora vamos ver os três tipos básicos de joins e como implementá-los:

1.  Inner Join

O Inner Join, que geralmente é a maneira mais utilizada de se retornar dados espalhados entre tabelas, funciona seguindo o princípio de que para os registros retornados de uma tabela, deve haver algum tipo de relação com os registros da outra tabela. No caso da igualdade, somente os registros das duas tabelas, que possuírem o mesmo valor para um determinado campo, são retornados. Um exemplo:

SELECT PED.PED_COD ,
PED. PED_DATA ,
ITEN. ITEN_COD ,
ITEN. ITEN_QTD
FROM PEDIDO PED , ITENSPEDIDO ITEN
WHERE
PED.PED_COD = ITEN.PED_COD

Percebam no exemplo acima que somente os registros que contiverem o mesmo valor para o campo PED_COD nas duas tabelas são retornados. Apesar de existir outra maneira de se fazer o INNER JOIN, eu recomendo a maneira com o WHERE, pois torna o código da instrução mais legível. Em termos de performance, as duas instruções se equivalem. Outra maneira, que retorna os mesmos resultados:

SELECT PED.PED_COD ,
PED. PED_DATA ,
ITEN. ITEN_COD ,
ITEN. ITEN_QTD
FROM PEDIDO PED INNER JOIN ITENSPEDIDO ITEN
ON PED.PED_COD = ITEN.PED_COD

É importante lembrar também que o Inner join permite o uso de outros operadores que não sejam somente o igual (=).

2Outer join

O tipo de join chamado Outer join, possui o funcionamento um pouco diferente. Utilizando o Outer join, além de podermos retornar os registros das duas tabelas seguindo alguma relação, ainda podemos retornar registros que não entram nesta relação.

Geralmente, este tipo de join pode ser utilizado em duas tabelas. Mas nada impede que se utilize em mais de duas tabelas, como a tabela de cliente ao nosso modelo PEDIDO-ITENS por exemplo.

Pensando na ligação entre duas tabela, foram criados duas opções para se utilizar no Outer Join:

* Opção LEFT OUTER JOIN, visando aplicar o conceito de Outer Join na tabela que se encontrar à esquerda da relação. Apesar de não ser recomendado, pode ser substituída pelo operador *=

* Opção RIGHT OUTER JOIN, visando aplicar o conceito de Outer Join na tabela que se encontrar à direita da relação. Apesar de não ser recomendado, pode ser substituída pelo operador =*

Como podemos alterar a ordem na qual colocamos a tabela na instrução, há um equivalência em termos de funcionalidade para estas opções de Outer Join. Importante: esta ordem é em relação às tabelas, e não à comparação feita após a palavra chave ON.

Por exemplo, queremos todos os pedidos que tenham relação com a tabela de itens e também os pedidos que não tenham relação com nenhum item:

SELECT PED.PED_COD ,
PED. PED_DATA ,
ITEN. ITEN_COD ,
ITEN. ITEN_QTD
FROM PEDIDO PED LEFT OUTER JOIN ITENSPEDIDO ITEN
ON PED.PED_COD = ITEN.PED_COD

Pode ser escrita como:

SELECT PED.PED_COD ,
PED. PED_DATA ,
ITEN. ITEN_COD ,
ITEN. ITEN_QTD
FROM ITENSPEDIDO ITEN RIGHT OUTER JOIN PEDIDO PED
ON PED.PED_COD = ITEN.PED_COD

ou ainda:

SELECT PED.PED_COD ,
PED. PED_DATA ,
ITEN. ITEN_COD ,
ITEN. ITEN_QTD
FROM ITENSPEDIDO ITEN , PEDIDO PED
WHERE PED.PED_COD *= ITEN.PED_COD

Vejam que para os registros em que a relação de igualdade foi encontrada, os campos de ambas as tabelas são retornados corretamente. Nos registros em que nenhum item de pedido foi encontrado, é colocado o valor NULL para todos os campos da tabela ITENSPEDIDO.

3Cross Join

O Cross Join possui uma funcionalidade completamente diferente dos outros tipos de Join. Ele simplesmente obtém todos os registros de todas as tabelas e faz o produto cartesiano (ou seja, cada registro de uma tabela é relacionado com cada registro da outra tabela), obtendo assim, o número total de registros através da multiplicação do total de registros das tabelas envolvidas no Cross Join.

Por exemplo:

SELECT PED.PED_COD ,
PED. PED_DATA ,
CLI.CLI_COD,
CLI.CLI_NOME
FROM PEDIDO PED , CLIENTE CLI

Percebam que no exemplo acima, todos os pedidos se relacionarão com todos os clientes, independendo do valor dos campos CLI_COD e PED_CLI.

Este tipo de Join poderia ser escrito e fazer dois Outer Join, que neste caso seria chamado de Full Outer Join. A partir da versão 2000 do SQL Server, não mais podemos utilizar o operador *=* para fazer Cross Join, pois este operador foi extinto.

Muitos problemas de query (como registros retornados a mais, ou duplicados, ou mesmo não atendendo o critério) ocorrem pelo mal uso de Joins. Para isso, temos uma pequena regra: SEMPRE que utilizarmos uma tabela na cláusula FROM de uma instrução SELECT, devemos obrigatoriamente fazer um join com alguma outra tabela que também está na cláusula FROM da instrução. Se simplesmente colocarmos a tabela na cláusula FROM e não fizermos nenhum join com ela, o SQL Server automaticamente irá fazer um Cross Join com as demais tabelas da instrução.

Leia Também:   Como definir uma máscara de entrada para um campo no Access