Para simplificar, suponha que todos os campos relevantes sejam NOT NULL
.
Você pode fazer:
SELECT
table1.this, table2.that, table2.somethingelse
FROM
table1, table2
WHERE
table1.foreignkey = table2.primarykey
AND (some other conditions)
Se não:
SELECT
table1.this, table2.that, table2.somethingelse
FROM
table1 INNER JOIN table2
ON table1.foreignkey = table2.primarykey
WHERE
(some other conditions)
Esses dois funcionam da mesma maneira MySQL
?
sql
mysql
join
inner-join
JCCyC
fonte
fonte
Respostas:
INNER JOIN
é a sintaxe ANSI que você deve usar.É geralmente considerado mais legível, especialmente quando você junta muitas tabelas.
Também pode ser facilmente substituído por um
OUTER JOIN
sempre que necessário.A
WHERE
sintaxe é mais orientada ao modelo relacional.Um resultado de duas tabelas
JOIN
ed é um produto cartesiano das tabelas às quais um filtro é aplicado que seleciona apenas as linhas com as colunas de junção correspondentes.É mais fácil ver isso com a
WHERE
sintaxe.Como no seu exemplo, no MySQL (e no SQL geralmente) essas duas consultas são sinônimos.
Observe também que o MySQL também possui uma
STRAIGHT_JOIN
cláusula.Usando esta cláusula, você pode controlar a
JOIN
ordem: qual tabela é varrida no loop externo e qual está no loop interno.Você não pode controlar isso no MySQL usando
WHERE
sintaxe.fonte
Oracle
,SQL Server
,MySQL
ePostgreSQL
- sim. Para outros sistemas, provavelmente também, mas é melhor verificar.WHERE
cláusula também está no padrão ANSI.@Bill Karwin
:JOIN
keyword não fazia parte dos padrões proprietários até o passado mais recente que possa parecer. Ele entrouOracle
apenas na versão9
ePostgreSQL
na versão7.2
(ambos lançados em2001
). A aparência dessa palavra-chave fazia parte daANSI
adoção padrão, e é por isso que essa palavra-chave geralmente está associadaANSI
, apesar do fato de que a última também suporta vírgula como sinônimoCROSS JOIN
.WHERE
cláusula (sem condições, uma junção é equivalente a uma junção cruzada, como você disse). O ANSI SQL-92 adicionou aJOIN
palavra - chave e a sintaxe relacionada, mas a sintaxe no estilo de vírgula ainda é suportada para compatibilidade com versões anteriores.Outros apontaram que
INNER JOIN
ajuda a legibilidade humana, e essa é uma prioridade, eu concordo.Deixe-me tentar explicar por que a sintaxe de junção é mais legível.
Uma
SELECT
consulta básica é esta:A
SELECT
cláusula nos diz o que estamos voltando; aFROM
cláusula nos diz de onde estamos obtendo e oWHERE
cláusula nos diz quais estamos obtendo.JOIN
é uma declaração sobre as tabelas, como elas são unidas (conceitualmente, na verdade, em uma única tabela).Quaisquer elementos de consulta que controlam as tabelas - de onde estamos obtendo coisas - pertencem semanticamente à
FROM
cláusula (e, é claro, é para onde osJOIN
elementos vão). Colocar elementos de junção naWHERE
cláusula conflita com o que e de onde , é por isso que aJOIN
sintaxe é preferida.fonte
Aplicando Instruções Condicionais em ON / WHERE
Aqui eu expliquei sobre as etapas do processamento de consultas lógicas.
Referência: Por dentro do Microsoft® SQL Server ™ 2005 T-SQL Querying
Editor: Microsoft Press
Pub Data: 07 de março de 2006
Imprimir ISBN-10: 0-7356-2313-9
Imprimir ISBN-13: 978-0-7356-2313-2
Páginas: 640
Por dentro do Microsoft® SQL Server ™ 2005 Consulta T-SQL
O primeiro aspecto perceptível do SQL que é diferente de outras linguagens de programação é a ordem na qual o código é processado. Na maioria das linguagens de programação, o código é processado na ordem em que está escrito. No SQL, a primeira cláusula processada é a cláusula FROM, enquanto a cláusula SELECT, que aparece primeiro, é processada quase por último.
Cada etapa gera uma tabela virtual usada como entrada para a etapa a seguir. Essas tabelas virtuais não estão disponíveis para o chamador (aplicativo cliente ou consulta externa). Somente a tabela gerada pela etapa final é retornada ao chamador. Se uma determinada cláusula não for especificada em uma consulta, a etapa correspondente será simplesmente ignorada.
Breve descrição das fases de processamento de consultas lógicas
Não se preocupe muito se a descrição das etapas não parece fazer muito sentido por enquanto. Estes são fornecidos como referência. As seções que vêm após o exemplo do cenário abordarão as etapas com muito mais detalhes.
FROM: um produto cartesiano (junção cruzada) é executado entre as duas primeiras tabelas na cláusula FROM e, como resultado, a tabela virtual VT1 é gerada.
LIGADO: O filtro LIGADO é aplicado ao VT1. Somente linhas para as quais
<join_condition>
é TRUE são inseridas no VT2.OUTER (junção): se um OUTER JOIN for especificado (em oposição a CROSS JOIN ou INNER JOIN), as linhas da tabela preservada ou as tabelas para as quais não foi encontrada uma correspondência serão adicionadas às linhas do VT2 como linhas externas, gerando VT3. Se mais de duas tabelas aparecerem na cláusula FROM, as etapas 1 a 3 serão aplicadas repetidamente entre o resultado da última associação e a próxima tabela na cláusula FROM até que todas as tabelas sejam processadas.
ONDE: O filtro ONDE é aplicado ao VT3. Somente linhas para as quais
<where_condition>
é TRUE são inseridas no VT4.GROUP BY: As linhas do VT4 são organizadas em grupos com base na lista de colunas especificada na cláusula GROUP BY. VT5 é gerado.
CUBO ROLLUP: Supergrupos (grupos de grupos) são adicionados às linhas do VT5, gerando VT6.
HAVING: O filtro HAVING é aplicado ao VT6. Somente grupos para os quais
<having_condition>
é TRUE são inseridos no VT7.SELECT: A lista SELECT é processada, gerando VT8.
DISTINCT: Linhas duplicadas são removidas do VT8. VT9 é gerado.
ORDER BY: As linhas do VT9 são classificadas de acordo com a lista de colunas especificada na cláusula ORDER BY. Um cursor é gerado (VC10).
TOPO: O número ou porcentagem de linhas especificado é selecionado desde o início do VC10. A tabela VT11 é gerada e retornada ao chamador.
Portanto, (INNER JOIN) ON filtrará os dados (a contagem de dados da VT será reduzida aqui) antes de aplicar a cláusula WHERE. As condições de junção subsequentes serão executadas com dados filtrados, o que melhora o desempenho. Depois disso, apenas a condição WHERE aplicará as condições de filtro.
(A aplicação de instruções condicionais em ON / WHERE não fará muita diferença em alguns casos. Isso depende de quantas tabelas você ingressou e do número de linhas disponíveis em cada tabela de ingresso)
fonte
A sintaxe implícita da junção ANSI é mais antiga, menos óbvia e não recomendada.
Além disso, a álgebra relacional permite a intercambiabilidade dos predicados na
WHERE
cláusula eINNER JOIN
, portanto, mesmoINNER JOIN
consultas comWHERE
cláusulas podem ter os predicados reorganizados pelo otimizador.Eu recomendo que você escreva as consultas da maneira mais legível possível.
Às vezes, isso inclui tornar o
INNER JOIN
"incompleto" relativamente e colocar alguns dos critérios noWHERE
simplesmente para facilitar a manutenção das listas de critérios de filtragem.Por exemplo, em vez de:
Escreva:
Mas isso depende, é claro.
fonte
Junções implícitas (que é conhecida como sua primeira consulta) se tornam muito mais confusas, difíceis de ler e difíceis de manter quando você precisa começar a adicionar mais tabelas à sua consulta. Imagine fazer a mesma consulta e tipo de junção em quatro ou cinco tabelas diferentes ... é um pesadelo.
O uso de uma associação explícita (seu segundo exemplo) é muito mais legível e fácil de manter.
fonte
Também apontarei que o uso da sintaxe mais antiga está mais sujeito a erros. Se você usar junções internas sem uma cláusula ON, você receberá um erro de sintaxe. Se você usar a sintaxe mais antiga e esquecer uma das condições de junção na cláusula where, receberá uma junção cruzada. Os desenvolvedores geralmente corrigem isso adicionando a palavra-chave distinta (em vez de corrigir a junção porque ainda não percebem que a junção está quebrada), que pode parecer curar o problema, mas diminuirá consideravelmente a consulta.
Além disso, para manutenção, se você tiver uma junção cruzada na sintaxe antiga, como o mantenedor saberá se você pretende ter uma (há situações em que são necessárias junções cruzadas) ou se foi um acidente que deve ser corrigido?
Deixe-me apontar para esta pergunta para ver por que a sintaxe implícita é ruim se você usa junções esquerdas. Sybase * = para Ansi Standard com 2 tabelas externas diferentes para a mesma tabela interna
Além disso (discurso pessoal aqui), o padrão que utiliza as junções explícitas tem mais de 20 anos, o que significa que a sintaxe implícita da junção está desatualizada nesses 20 anos. Você escreveria código de aplicativo usando sintaxe desatualizada por 20 anos? Por que você deseja escrever o código do banco de dados?
fonte
HAVING
'desatualizado' desde que o SQL começou a suportar tabelas derivadas. Percebo também que você não usa,NATURAL JOIN
mesmo que eu argumentasse que ficouINNER JOIN
"desatualizado". Sim, você tem suas razões (não há necessidade de declará-las novamente aqui!): Meu argumento é que aqueles que gostam de usar a sintaxe mais antiga também têm suas razões e a idade relativa da sintaxe é de pouca ou nenhuma relevância.Eles têm um significado legível para humanos.
No entanto, dependendo do otimizador de consulta, eles podem ter o mesmo significado para a máquina.
Você deve sempre codificar para ser legível.
Ou seja, se esse é um relacionamento interno, use a associação explícita. se você estiver correspondendo a dados pouco relacionados, use a cláusula where.
fonte
O padrão SQL: 2003 alterou algumas regras de precedência para que uma instrução JOIN tenha precedência sobre uma junção "vírgula". Na verdade, isso pode alterar os resultados da sua consulta, dependendo de como está configurada. Isso causa alguns problemas para algumas pessoas quando o MySQL 5.0.12 mudou para aderir ao padrão.
Portanto, no seu exemplo, suas consultas funcionariam da mesma forma. Mas se você adicionou uma terceira tabela: SELECT ... FROM tabela1, tabela2 JOIN table3 ON ... WHERE ...
Antes do MySQL 5.0.12, a tabela1 e a tabela2 seriam unidas primeiro, depois a tabela3. Agora (5.0.12 e diante), tabela2 e tabela3 são unidas primeiro, depois tabela1. Nem sempre muda os resultados, mas pode e você pode nem perceber.
Eu nunca mais uso a sintaxe "vírgula", optando pelo seu segundo exemplo. De qualquer forma, é muito mais legível, as condições JOIN estão com os JOINs, não separadas em uma seção de consulta separada.
fonte
Eu sei que você está falando sobre o MySQL, mas de qualquer maneira: no Oracle 9 junções explícitas e junções implícitas gerariam planos de execução diferentes. AFAIK que foi resolvido no Oracle 10+: não existe mais essa diferença.
fonte
A sintaxe de junção ANSI é definitivamente mais portátil.
Estou passando por uma atualização do Microsoft SQL Server e também mencionaria que a sintaxe = * e * = para associações externas no SQL Server não é suportada (sem modo de compatibilidade) para o servidor sql de 2005 e versões posteriores.
fonte
*=
e=*
nunca foram ANSI e nunca foram uma boa notação. É por isso que ON foi necessário - para as junções externas na ausência de subselects (que foi adicionado ao mesmo tempo, para que eles não são realmente necessários em CRUZ & associações internas.)Se você costuma programar procedimentos armazenados dinâmicos, se apaixona pelo seu segundo exemplo (usando where). Se você tiver vários parâmetros de entrada e muita confusão de metamorfose, essa é a única maneira. Caso contrário, ambos executarão o mesmo plano de consulta, portanto, definitivamente não haverá diferença óbvia nas consultas clássicas.
fonte