Usando a palavra-chave JOIN ou não

40

As seguintes consultas SQL são as mesmas:

SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;

SELECT column1, column2
FROM table1 JOIN table2 
ON table1.id = table2.id;

E certamente resultará nos mesmos planos de consulta em todos os DBMSs que já tentei.

Mas de vez em quando eu leio ou ouço uma opinião de que alguém é definitivamente melhor do que o outro. Naturalmente, essas alegações nunca são substanciadas explicação.

Onde eu trabalho, a segunda versão parece ser favorecida pela maioria dos outros Devs, e assim eu também tendem a esse estilo para minimizar a surpresa. Mas na minha coração, eu estou realmente pensando o primeiro (desde que eu aprendi originalmente isso.

Uma dessas formas é objetivamente melhor que a outra? Se não, quais seriam as razões para usar uma sobre a outra?

    
por SingleNegationElimination 22.05.2011 / 03:19
fonte

9 respostas

57

Acho que a segunda forma é melhor. Isso pode ser porque foi assim que aprendi, admito, mas tenho uma razão concreta - separação de interesses. Colocar os campos que você está usando para unir as tabelas na cláusula where pode levar a dificuldades em entender as consultas.

Por exemplo, faça a seguinte consulta:

select *
from table1, table2, table3, table4
where table1.id = table2.id
and table2.id = table3.id
and table3.id = table4.id
and table1.column1 = 'Value 1'

A consulta acima tem condições de união de tabelas e condições reais de lógica de negócios, todas combinadas em um único espaço. Com uma consulta grande, isso pode ser muito difícil de entender.

No entanto, agora pegue este código:

select *
from table1 join table2 on table1.id = table2.id
join table3 on table2.id = table3.id
join table4 on table3.id = table4.id
where table1.column1 = 'Value 1'

Nesse caso, qualquer coisa que tenha a ver com as tabelas ou como elas se relacionam é toda isolada para a cláusula from, enquanto a lógica de negócios real para restrição de consulta está na cláusula where. Acho que isso é muito mais compreensível, principalmente para consultas maiores.

    
por 22.05.2011 / 03:27
fonte
36

A sintaxe de junção substituiu a antiga sintaxe por vírgula em 1992. Não há atualmente nenhuma razão para escrever código com a sintaxe de vírgula. Você não ganha nada e está sujeito a alguns problemas que simplesmente não tem com a sintaxe explícita.

Em primeiro lugar, à medida que você obtém consultas mais complicadas, é muito fácil fazer uma junção cruzada acidental, perdendo uma condição where. Isso é algo que a sintaxe de junção explícita pode impedir que aconteça, pois você obterá um erro de sintaxe.

Se você pretende uma junção cruzada, a sintaxe de junção explícita deixará isso claro, enquanto na sintaxe implícita alguém fazendo manutenção pode supor que você esqueceu de adicionar a cláusula where.

Em seguida, há o problema de junções esquerda e direita que são problemáticas em pelo menos alguns dbs usando a sintaxe implícita. Eles estão obsoletos no SQL Server e, na verdade, não retornam resultados corretos de forma real, mesmo nas versões mais antigas. Nenhuma consulta que precise de uma associação externa deve conter a sintaxe implícita no SQL Server.

Além disso, tenho visto perguntas aqui e em outros sites onde resultados errados aconteceram quando as pessoas misturaram as junções implícitas e explícitas (ao adicionar uma junção à esquerda, por exemplo), então é uma má idéia misturá-las.

Finalmente, muitas pessoas que usam associações implícitas na verdade não entendem junções. Este é um entendimento crítico que você deve ter para efetivamente consultar um banco de dados.

    
por 22.05.2011 / 04:57
fonte
7

Acabei de encontrar uma possível resposta à minha própria pergunta, enquanto observava a documentação do PostgreSQL . Para resumir o que esta página explica, a consulta resultante ainda é a mesma, mas o número de planos que o otimizador deve considerar cresce exponencialmente com o número de junções.

Após cerca de seis dessas junções, o número é tão grande que o tempo para planejar a consulta pode ser perceptível e, após cerca de dez, o otimizador passa de uma pesquisa exaustiva de planos para uma pesquisa probabilística e pode não chegar o plano ideal.

Ao definir um parâmetro de tempo de execução, você pode instruir o planejador a tratar junções internas e cruzadas explicitamente mencionadas de forma diferente das associações implícitas, forçando-as para o início do plano e não explorando outras opções.

É importante observar que o comportamento padrão é o mesmo em ambos os casos, e que a obtenção de planos alternativos requer conhecimento dos internos do dbms e as peculiaridades das tabelas em questão para obter um resultado diferente

    
por 22.05.2011 / 04:04
fonte
7

Bem, aqui está a visão da teoria dos conjuntos:

Quando você usa uma vírgula para separar dois (ou mais) nomes de tabelas, o que você está pretendendo é o produto cartesiano. Cada linha da tabela 'esquerda' será 'correspondida' (concatenada) com aquela da tabela da direita.

Agora, se você escrever algo na cláusula where, é como colocar uma condição nessa "concatenação" informando quais linhas "concatenar" com quais linhas.

Na verdade, isso está "unindo" as linhas :) e, portanto, a palavra-chave join ajuda a fornecer uma sintaxe mais legível e é mais compreensível que você "realmente" deseje ingressar em alguns valores comuns. Semelhante ao que o @Dustin esclareceu acima.

Agora, todo SGBD é inteligente, ou seja, ele não calcula o produto cartesiano primeiro e depois filtra os dados (extremamente desperdiçador), mas o faz com base na estrutura da consulta. A única coisa que posso pensar é, quando você pede para 'juntar', é como tornar a atividade de junção explícita e provavelmente ajuda a executar o código mais rápido (em quanto? Você terá que fazer o perfil e ver), mas no Caso separado por vírgulas, é necessário algum tempo para 'descobrir' a melhor estratégia. Eu posso estar errado, mas eu estou apenas fazendo um palpite sobre como alguém poderia codificá-lo ...

    
por 22.05.2011 / 12:15
fonte
4

Acho que geralmente é melhor usar as instruções JOIN para esse caso.

Se, no futuro, surgir uma situação que exija a alteração da declaração de um INNER JOIN para um OUTER JOIN, isso será muito mais fácil de fazer com a segunda instrução.

    
por 22.05.2011 / 03:24
fonte
2

Qualquer RDBMS fará com que sejam a mesma coisa em termos de execução. Tudo se resume a se é mais legível e expressivo.

Use o JOIN para que fique claro o que é a correspondência de união e a seleção real, como em:

select name, deptname
from people p, departments d
where p.deptid = d.id and p.is_temp = 'Y'

vs.

select name, deptname
from people p
    inner join departments d on p.deptid = d.id
where p.is_temp = 'Y'

O último caso torna claro imediatamente qual é a condição de junção e qual é o critério de seleção.

    
por 22.05.2011 / 03:57
fonte
1

Eu só vi uma vez os dois resultados em um conjunto diferente de otimizações e se a memória serve foi em ms-sql2k em uma consulta muito peludo. Nesse exemplo, a forma antiga usada com * = resultou em desempenho cerca de 4x mais rápido. Ninguém, incluindo nossos técnicos da Microsoft, poderia explicar o porquê. Os caras da MS rotularam isso como um erro. Eu nunca mais vi isso.

Como a maioria dos RDBMS é inteligente o suficiente para não fazer os cartesianos completos, a maior razão que posso pensar em não usá-los (além disso, é depreciado) é que a maioria das pessoas com menos de 30-35 anos com quem eu trabalhei nunca vi a velha forma antes e se perdem quando a encontram.

    
por 23.05.2011 / 21:49
fonte
-1

O estilo antigo foi preterido, você não deve usá-lo.

Não deveria haver sequer uma discussão sobre qual é melhor ou não. O novo código não deve usar a sintaxe antiga.

    
por 23.04.2015 / 09:39
fonte
-4

Um motivo para a sintaxe mais concisa é que ela é mais concisa, então, se você se sentir confortável com ela, será mais fácil de ler. Penso no caso detalhado como semelhante a escrever aritmética em COBOL, por ex. MULTIPLY A BY B DANDO C.

    
por 22.05.2011 / 12:42
fonte