Tutoriais » SQL » Junção Complementares » Definindo:
Este comando coloca lado-a-lado as tuplas de duas tabelas que atendam a uma condição de comparação de campos,
exibindo todas as linhas de uma tabela (mesmo que não emparelhadas). Em livros o termo 'lado-a-lado' pode ser escrito: EMPARELHAR. Simbologia AR: A ][ condição ]] B ou A ⟕ B A [[ condição ][ B ou A ⟖ B A ][ condição ][ B ou A ⟗ B
Exemplo de uma expressão de AR para uma junção aberta pela esquerda. Note onde aparece escrita a condição da junção. Funcionarios ⟕_{Funcionários.funcaoid = funcoes.idfuncao} funcoes Sintaxe: select * from <tabela1> [left | rigth | full outer] <tabela2> ON <condição de valores dos campos> Notas:
Repare na estrutura da Sintaxe apresentada acima: o LEFT indica ao SGBD que a tabela com nome escrito à ESQUERDA do operador JOIN a tabela completa, ou seja,
TODAS as linhas da tabela da esquerda devem ser exibidas no resultado do comando.
As linhas da tabela da ESQUERDA que não ficam emparelhadas atendendo à condição aparecem ao lado de linhas com valores nulos do lado da DIREITA.
Podemos trocar left por right, esquerda por direita e direita por esquerda e a frase anterior continua peferitamente certa. Leia.
Repare na estrutura da Sintaxe apresentada acima: o RIGHT indica ao SGBD que a tabela com nome escrito à DIREITA do operador JOIN a tabela completa, ou seja,
TODAS as linhas da tabela da DIREITA devem ser exibidas no resultado do comando.
As linhas da tabela da DIREITA que não ficam emparelhadas atendendo à condição aparecem ao lado de linhas com valores nulos do lado da ESQUERDA.
Lembre-se dos padrões da SQL. Consulte a página deste tutorial que comenta a evolução dos padrões.
No padrão de 87 não existia o operador JOIN. Entretanto, uma junção aberta podia ser implementada com a combinação de comandos SQL.
Analise os exemplos abaixo: select funcionarios.* from funcionarios, funcoes where funcionarios.funcaoid = funcoes.idfuncao; Esse comando é uma projeção de uma junção.
É como fazer uma Junção e da tabela Resultado Projetar somente os campos de uma das tabelas (obtendo SOMENTE as linhas ligadas pela junção).
Então, SE de TODOS os funcionarios fossem subtraídos os funcionarios que têm relação com funções, sobraria os funcionários que NÃO têm relação com funções.
Para fazer esta subtraçao, escreve-se: select * from funcionarios EXCEPT (select funcionarios.* from funcionarios, funcoes where funcionarios.funcaoid = funcoes.idfuncao); Neste comando o operador EXCEPT faz a subtração 'tirando' da tabela indicada na esquerda todas as linhas que também aparecem na tabela indicada na direita.
Note que nesse comando não foi usado o operador JOIN. Essa era uma das formas de se fazer uma junção aberta descobrindo linhas de uma tabela não relacionadas com outras.
Porém isso não era nada prático. Esse foi um dos motivos que levaram ao desenvolvimento do operador JOIN.
Analise (novamente, se quiser execute este comando em uma aba de um query tool do pg Admin 4 ou programa equivalente em outro gerenciador): select funcionarios.* from funcionarios left join funcoes on funcionarios.funcaoid = funcoes.idfuncao where idfuncao is null; Executando este comando no servidor, o que foi visto como resposta desse comando?
Analise o comando: select * from funcionarios except (select funcionarios.* from funcionarios inner join funcoes on funcionarios.funcaoid = funcoes.idfuncao) ; Execute este comando no servidor. Parece 'mais simples' que o comando da nota anterior? Tem analista e programadores que preferem a sintaxe ANSI:87
Observando a junção aberta (teste no ambente do servidor de dados).
Executando o comando SELECT * FROM funcionarios;
Consegue-se ver as TODAS as linhas da tabela funcionarios.
A tabela funcionarios tem uma ligação com a tabela departamentos. Esta ligação pode ser vista com o comando: SELECT * FROM funcionarios INNER JOIN departamentos ON funcionarios.deptoid=departamentos.deptoid;
Note que a quantidade de linhas recuperada é menor do que no comando anterior, ou seja, existem funcionarios NÃO ligados aos departamentos... Pergunta:
Quais são os funcionarios que não tem ligação com departamento? SELECT * FROM funcionarios LEFT JOIN departamentos ON funcionarios.deptoid=departamentos.deptoid;
Bem, sobre o resultado da Junção aberta, fazendo uma seleção... SELECT * FROM funcionarios LEFT JOIN departamentos ON funcionarios.deptoid=departamentos.deptoid WHERE departamentos.iddepto IS NULL;
E do resultado desse comando, fazendo uma projeção... SELECT funcionarios.*
FROM funcionarios LEFT JOIN departamentos ON funcionarios.deptoid=departamentos.deptoid
WHERE departamentos.iddepto IS NULL;
Finalmente, a lista de funcionairos que NÃO tem ligação com nenhum departamentos.
De outro modo podemos querer saber:
Existem departamentos sem funcionarios ligados a eles, se sim, quais são estes departamentos? SELECT departamentos.*
FROM funcionarios RIGHT JOIN departamentos ON funcionarios.deptoid=departamentos.deptoid
WHERE funcionarios.id_funcionario IS NULL;
Ainda é preciso citar nesse tutorial a junção completa (lá sintaxe se vê o complemento FULL OUTER do operador JOIN.
Para isso se constroem tabelas auxiliares (func e funcoes) com os 2 comandos: create temporary table func as (select f.idfuncionario, f.txprenomes, f.txsobrenome, f.funcaoid from funcionarios as f); create table funcao as (select f.idfuncao, f.txnomefuncao from funcoes as f);
Uma vez construídas as tabelas, pode-se escrever o comando que faz a junção completa escrevendo: select * from func full outer join funcao on func.funcaoid = funcao.idfuncao;
Uma nota sobre a flexibilidade de combinação de comandos que é possível com a SQL. Os comandos da nota anterior podem ser escritos em um só comando, na forma select * from (select f.idfuncionario, f.txprenomes, f.txsobrenome, f.funcaoid from funcionarios as f) as func
full outer join
(select f.idfuncao, f.txnomefuncao from funcoes as f) as funcao
on func.funcaoid = funcao.idfuncao;
Sem a necessidade de criar as tabelas temporárias