Porque é que você deve repensar as suas consultas (queries)
Entendendo o que é um JOIN implícito, um JOIN explícito e as suas diferenças
Como cientista de dados consultas em bancos de dados fazem parte do meu dia-a-dia.
Para tal, trazer a informação de uma forma precisa e construir as consultas de modo a que sejam facilmente revisitadas é essencial, pois não só diminuem os possíveis erros como é economizado muito tempo em todo o processo de manutenção.
No entanto, para chegar nesse nível ideal de consultas é necessário entender as pequenas variações do comportamento destas.
Contudo como ninguém nasce especialista, vamos entendendo uma por vez, seja por necessidade, seja por curiosidade, essa pelo menos é a minha filosofia.
Feita a introdução vamos ao desafio, considere o seguinte cenário:
O seu chefe lhe pediu uma lista com o cargo de cada funcionário da empresa A.
Você abre o seu banco de dados e vê que existem estas duas tabelas:
Funcionarios
e
Cargos
Está fácil, não é? (Queria eu que as consultas reais fossem nesse nível, mas vamos focar num exemplo simples).
Você imediatamente começa a escrever a consulta e o resultado final é:
SELECT Funcionarios.ID, nome, empresa, cargo_ID, cargo
FROM Funcionarios
INNER JOIN Cargos
ON Funcionarios.cargo_ID = Cargos.ID
WHERE Funcionarios.empresa = "A";
Exporta a lista e entrega para o seu chefe, trabalho concluído. Palmas para você.
O que o seu chefe não lhe disse é que também passou a mesma tarefa para um outro colega seu, apenas com o intuito de levantar uma discussão (afinal quem não gosta de uma boa treta!).
5 minutos depois o seu chefe lhe chama, mostra a solução do seu colega e lhe pergunta: Qual a diferença entre a seguinte consulta e a sua?
SELECT Funcionarios.ID, nome, empresa, cargo_ID, cargo
FROM Funcionarios, Cargos
WHERE Funcionarios.cargo_ID = Cargos.ID
AND Funcionarios.empresa = "A";
Pois é, o que o seu chefe não mencionou é que ele está de sacanagem com você.
Você acabou de presenciar uma pegadinha:
As duas consultas produzem o mesmo resultado!
Porém, elas não são iguais.
No entanto, se você se sentiu tentado a mudar a sua consulta eu vou tentar exorcizar esse pensamento para todo o sempre.
Mas vamos por partes, o que você acabou de presenciar não é nada mais que a diferença entre um JOIN implícito (2ª versão) e um explícito (1ª versão).
O que me traz ao primeiro ponto:
#1. Ao usar a versão implícita você delega a escolha da junção entre tabelas
E quando se trata de deixar claro de onde e como a informação está vindo o simples fato de delegar uma escolha pode trazer complicações futuras (mais informação sobre isso adiante).
Então se você pode escolher, opte sempre por versões explícitas, garantindo assim a clareza da sua escolha no momento da construção da consulta.
Por baixo dos panos o que acontece é que por defeito quando é solicitado um JOIN implícito com uma condição (WHERE Funcionarios.cargo_ID = Cargos.ID AND Funcionarios.empresa = “A”) é realizado um INNER JOIN.
O que me leva para o segundo ponto:
#2. E se você esqueceu da condição?
Num cenário com apenas duas tabelas isso não acontece, mas quando se trata de consultas complexas facilmente chamamos várias tabelas, e consequentemente a possibilidade de esquecermos uma condição de relação entre elas aumenta.
Quando usamos o JOIN implícito, e não é declarada uma condição, por defeito é realizado um CROSS JOIN, que para os mais esquecidos é o produto cartesiano entre as tabelas.
Que no nosso caso seria uma tabela com n linhas de funcionários por n cargos.
SELECT Funcionarios.ID, nome, empresa, cargo_ID, Cargos.ID, cargo
FROM Funcionarios, Cargos
WHERE Funcionarios.empresa = "A";
(Reparou que passamos de uma tabela de 3 linhas para 9?!)
Diferentemente do que acontece com um JOIN implícito, no JOIN explícito se a condição não for declarada a consulta simplesmente dá erro.
Nos trazendo para o terceiro ponto:
#3. Manutenção
Dois anos se passaram desde aquela pegadinha do seu chefe, e ele lhe pede para fazer um ajuste numa consulta que o seu colega, que, entretanto, mudou de empresa, fez naquela mesma época.
Você abre a consulta e se depara com uma infinidade de JOINs implícitos e quando começa a analisar as condições uma por uma, vê que não foi declarada uma condição de relação entre tabelas.
Surgindo a pergunta: O meu ex-colega esqueceu a condição, ou de fato a consulta está correta e ele queria fazer um CROSS JOIN?
No entanto, ninguém documentou o objetivo daquela consulta e você está deduzindo-o ao olhar para a consulta. Como você já está na empresa há dois anos você consegue ver uma realidade onde os dois cenários (com e sem condição) fazem sentido, além disso, neste momento talvez nem o seu antigo colega saiba mais qual seria a versão correta.
Com um JOIN explícito, como a consulta não iria funcionar sem condições, e caso existisse de fato um CROSS JOIN ele teria que ser declarado, então este problema não se levantaria.
Além disso, com os JOINs explícitos a consulta se torna muito mais legível (quem não gosta de uma leitura mais agradável?). Dessa forma, você consegue acompanhar JOIN por JOIN o que está acontecendo.
Lembra do princípio do código modular?
Acaba sendo quase isso, cada JOIN explícito representa um módulo, então você pode ir diretamente nele e alterá-lo se já conhecer o problema, em vez de percorrer todas as condições para determinar as relações entre tabelas.
Se ainda não se convenceu tenho mais uns pontos extra para você:
#4. Com um JOIN explícito existe controle da ordem da execução
#5. Desde de 1992 que o JOIN explícito foi definido como o padrão a ser adotado (isso mesmo, quase 30 anos atrás!!!)
Mais especificamente no SQL-92 que foi a terceira revisão da linguagem.
(Se o guerreiro dentro de ti quiser enfrentar um desafio extra podes consultar a revisão aqui).
Resumindo, no final do dia cabe a você questionar suas próprias consultas: Elas estão trazendos os resultados necessários? Existem chances de imprecisões? Mas acima de tudo, o seu objetivo é claro o suficiente? Se não, consegue deixá-lo mais claro, ou precisa de documentar alguma coisa pelo caminho?
Então depois disto eu te pergunto:
Qual é o tipo de consulta que vais usar?
P.S.: Se lembrou de algum outro ponto, ou não concordo com algum dos pontos mencionados? Comente ou fale comigo no Linkedin e vamos juntos melhorar este conteúdo.
Fontes de informações:
- Wikipedia | SQL
- Wikipedia | SQL-92
- SQL-92
- Stackoverflow |SQL left join vs multiple tables on FROM line?