A ordem de junção é importante no SQL?

189

Desconsiderando o desempenho, obterá o mesmo resultado da consulta A e B abaixo? E quanto a C e D?

-- A
select *
from   a left join b
           on <blahblah>
       left join c
           on <blahblan>


-- B
select *
from   a left join c
           on <blahblah>
       left join b
           on <blahblan>  

-- C
select *
from   a join b
           on <blahblah>
       join c
           on <blahblan>


-- D
select *
from   a join c
           on <blahblah>
       join b
           on <blahblan>  
Apenas um aprendiz
fonte
11
O que é <blahblah>? você está juntando A a B e A a C, ou você está juntando A a B e B a C?
beny23
2
Oi Beny, o código na minha pergunta é uma abstração. Não estou preocupado em juntar A a B ou A a C, só quero saber se a sintaxe assim fornecerá resultados idênticos.
Apenas um aluno

Respostas:

225

Para INNERjunções, não, o pedido não importa. As consultas retornarão os mesmos resultados, desde que você altere suas seleções de SELECT *para SELECT a.*, b.*, c.*.


Para ( LEFT, RIGHTou FULL) OUTERjunções, sim, a ordem é importante - e ( atualizadas ) as coisas são muito mais complicadas.

Primeiro, as junções externas não são comutativas; portanto, a LEFT JOIN bnão é o mesmo queb LEFT JOIN a

Junções externas também não são associativas, portanto, em seus exemplos que envolvem as propriedades (comutatividade e associatividade):

a LEFT JOIN b 
    ON b.ab_id = a.ab_id
  LEFT JOIN c
    ON c.ac_id = a.ac_id

é equivalente a :

a LEFT JOIN c 
    ON c.ac_id = a.ac_id
  LEFT JOIN b
    ON b.ab_id = a.ab_id

mas:

a LEFT JOIN b 
    ON  b.ab_id = a.ab_id
  LEFT JOIN c
    ON  c.ac_id = a.ac_id
    AND c.bc_id = b.bc_id

não é equivalente a :

a LEFT JOIN c 
    ON  c.ac_id = a.ac_id
  LEFT JOIN b
    ON  b.ab_id = a.ab_id
    AND b.bc_id = c.bc_id

Outro exemplo (talvez mais simples) de associatividade. Pense nisso como (a LEFT JOIN b) LEFT JOIN c:

a LEFT JOIN b 
    ON b.ab_id = a.ab_id          -- AB condition
 LEFT JOIN c
    ON c.bc_id = b.bc_id          -- BC condition

Isso é equivalente a a LEFT JOIN (b LEFT JOIN c):

a LEFT JOIN  
    b LEFT JOIN c
        ON c.bc_id = b.bc_id          -- BC condition
    ON b.ab_id = a.ab_id          -- AB condition

somente porque temos ONcondições "agradáveis" . Ambos ON b.ab_id = a.ab_ide c.bc_id = b.bc_idsão verificações de igualdade e não envolvem NULLcomparações.

Você pode até ter condições com outros operadores ou outros mais complexos, como: ON a.x <= b.xou ON a.x = 7ou ON a.x LIKE b.xou ON (a.x, a.y) = (b.x, b.y)e as duas consultas ainda seriam equivalentes.

Se, no entanto, qualquer um desses envolvidos IS NULLou uma função relacionada a nulos COALESCE(), como , por exemplo, se a condição fosse b.ab_id IS NULL, as duas consultas não seriam equivalentes.

ypercubeᵀᴹ
fonte
3
É mais correto dizer que a junção externa é associativa desde que nenhum predicado possa ser satisfeito por uma linha na qual todas as colunas de uma tabela são NULL, do que dizer que é associativa desde que os predicados não envolvam IS NULL ou 'uma função relacionada a nulos'. Pode-se facilmente imaginar um predicado que satisfaça a descrição anterior, mas não a última, como a.somecol > 0 OR b.someothercol > 0; a associatividade pode falhar para essa condição.
Mark Amery
Mas sim, acho que é tecnicamente verdade dizer que OUTER JOIN é associativo, desde que o predicado não atenda a nenhuma das condições descritas aqui: stackoverflow.com/questions/20022196/… (a primeira das quais também quebra a associatividade para INNER JOINs, mas é uma abordagem tão barata e óbvia para quebrá-lo que talvez não mereça ser mencionada.) Também vale a pena ressaltar que o tipo mais comum de JOIN - JOIN em uma chave estrangeira - não atende a nenhuma dessas condições e, portanto, é agradável e associativo.
Mark Amery
1
@MarkAmery Obrigado, eu estava tendo um momento difícil estruturação minhas frases sobre este ponto (e eu já upvoted essa resposta de vocês;)
ypercubeᵀᴹ
ypercube eu tenho um INNER JOINe um seguinte LEFT JOIN. Funciona assim primeiro, a consulta será Filterbaseada nos registros INNER JOINe depois será aplicada LEFT JOINaos Filteredregistros?
Muhammad Babar
De fato, todos os tipos de junção são associativos, conforme especificado pelo padrão SQL e de acordo com definições matemáticas de associatividade, mas não parecem associativos, pois reorganizar os parênteses exige mover a ONcláusula (ou seja, a "especificação de junção") para um novo local . Isso é apenas sintaxe, no entanto. Se você usar a notação de álgebra relacional (onde a especificação de junção é colocada abaixo do operador de junção), a associatividade se tornará mais evidente. Seu argumento é exibida apenas que as junções externas não são comutativa , que está correto
Lukas Eder
4

para junções regulares, isso não acontece. TableA join TableBproduzirá o mesmo plano de execução que TableB join TableA(para que seus exemplos de C e D sejam os mesmos)

para junções esquerda e direita, ele faz. TableA left Join TableBé diferente de TableB left Join TableA, mas é o mesmo queTableB right Join TableA

Diego
fonte
4
Isso aborda apenas a comutatividade, mas os exemplos na pergunta mostram que o solicitante está interessado em associatividade. A resposta do ypercube trata de ambos.
Mark Amery
2

Se você tentar unir C em um campo de B antes de ingressar em B, ou seja:

SELECT A.x, A.y, A.z FROM A 
   INNER JOIN C
       on B.x = C.x
   INNER JOIN b
       on A.x = B.x

sua consulta falhará, portanto, nesse caso, o pedido é importante.

Teo J.
fonte
Sim, está certo, a resposta correta deve ser alterada.
Nir Pengas
-2

O otimizador Oracle escolhe a ordem de junção das tabelas para junção interna. O Optimizer escolhe a ordem de junção das tabelas apenas em cláusulas FROM simples. Você pode verificar a documentação do oracle em seu site. E para a esquerda, a junção externa direita, a resposta mais votada é a correta. O otimizador escolhe a ordem de junção ideal e o índice ideal para cada tabela. A ordem de junção pode afetar qual índice é a melhor escolha. O otimizador pode escolher um índice como o caminho de acesso para uma tabela se for a tabela interna, mas não se for a tabela externa (e não houver mais qualificações).

O otimizador escolhe a ordem de junção das tabelas apenas em cláusulas FROM simples. A maioria das junções que usam a palavra-chave JOIN é achatada em junções simples; portanto, o otimizador escolhe sua ordem de junção.

O otimizador não escolhe a ordem de junção para junções externas; ele usa a ordem especificada na instrução

Ao selecionar uma ordem de junção, o otimizador leva em consideração: O tamanho de cada tabela Os índices disponíveis em cada tabela Se um índice em uma tabela é útil em uma ordem de junção específica O número de linhas e páginas a serem verificadas para cada tabela em cada ordem de junção

Saumyojit Das
fonte