Eu tenho duas versões de uma junção múltipla que produzem resultados idênticos. As cinco tabelas são:
customers ← sales ← saleitems → paintings → artists
As setas (espero) mostram a relação entre as tabelas.
Cada tabela tem uma chave primária chamada id
, e as tabelas internas têm uma chave estrangeira para outra tabela chamada [othertable]id
.
A primeira versão é uma junção clássica com a tabela listada na ordem acima
SELECT
c.id, c.givenname, c.familyname,
a.givenname, a.familyname
FROM
customers c
JOIN sales s ON c.id=s.customerid
JOIN saleitems si ON s.id=si.saleid
JOIN paintings p ON si.paintingid=p.id
JOIN artists a ON p.artistid=a.id
;
A segunda versão contém todas as JOIN
cláusulas primeiro, e as ON
cláusulas, na ordem inversa .
SELECT
c.id, c.givenname, c.familyname,
a.givenname, a.familyname
FROM
customers c
JOIN sales s
JOIN saleitems si
JOIN paintings p
JOIN artists a
ON p.artistid=a.id
ON si.paintingid=p.id
ON s.id=si.saleid
ON c.id=s.customerid
;
OK, então funciona, mas alguém pode explicar como funciona a segunda versão? Por que a ordem das ON
cláusulas deve ser o inverso das JOIN
cláusulas? É possível ordenar aleatoriamente as cláusulas JOIN
ou ?ON
Eu testei isso no Microsoft SQL e também no PostgreSQL.
Você não pode randomizá-los, a ordem é importante. Talvez você possa ver mais claramente se adicionarmos alguns parênteses entre as junções.
O que essa consulta está fazendo é unir primeiro e,
sales
emsaleitems
seguida, seu resultado está sendo unido comcustomers
. Você não pode fazer referência a umacustomers
coluna dentro da junção de parênteses porque ela não está acessível:Se você me perguntar, eu ficaria com a primeira maneira de escrever a consulta, é muito mais clara para a maioria dos programadores dessa maneira.
A sintaxe JOIN na maioria dos casos requer que ambos JOIN e ON estejam presentes (a menos que algumas situações específicas como CROSS JOIN para as quais ON não faria nenhuma diferença). Considere que isso seja semelhante a
BEGIN..END
declarações - elas têm que ser aEND
declaração relacionada ao anterior mais próximo,BEGIN
comoÉ por isso que funcionou quando você colocou as cláusulas ON na ordem inversa. Mas não é uma boa prática, porque será demorado determinar qual condição se relaciona a quais tabelas. Especialmente se você perder o recuo/formatação no caminho.
Além disso, o recuo extra para o 2º e todos os próximos JOINS é desnecessário. A ordem das
JOIN
cláusulas geralmente não importa (a menos que você use uma dica de consulta que force o otimizador a fazer isso).Eu, pessoalmente, acharia muito mais limpo como abaixo (+ declare explicitamente INNER JOIN, + organize junções começando com a tabela 'fato' em que você está interessado, outras tabelas são descrições dos fatos que você está recuperando, opcionalmente se importante, eu coloque cada coluna em uma linha separada - se não for importante, geralmente as coloco em uma linha). Mas, novamente, isso é coisa de estilo de codificação individual.