Pergunta sobre oracle11g, sql, join, oracle – Você pode ter um INNER JOIN sem a palavra-chave ON?

15

Enquanto depuração em algum código Oracle, me deparei com essa consulta:

SELECT TPM_TASK.TASKID FROM TPM_GROUP 
INNER JOIN TPM_USERGROUPS ON TPM_GROUP.GROUPID = TPM_USERGROUPS.GROUPID 
INNER JOIN TPM_TASK
INNER JOIN TPM_GROUPTASKS ON TPM_TASK.TASKID = TPM_GROUPTASKS.TASKID 
INNER JOIN TPM_PROJECTVERSION ON TPM_TASK.PROJECTID = TPM_PROJECTVERSION.PROJECTID AND TPM_TASK.VERSIONID = TPM_PROJECTVERSION.VERSIONID 
INNER JOIN TPM_TASKSTAGE ON TPM_TASK.STAGEID = TPM_TASKSTAGE.STAGEID 
INNER JOIN TPM_PROJECTSTAGE ON TPM_PROJECTVERSION.STAGEID = TPM_PROJECTSTAGE.STAGEID 
ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID

Estou confuso com a linha:

INNER JOIN TPM_TASK

Eu não vi umJOIN sem umON cláusula anterior. Também confuso é a linha:

ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID

Isso parece ser aleatórioON cláusula sem qualquer correspondênciaJOIN. A consulta é executada sem erros e retorna um monte de dados, portanto, a sintaxe é perfeitamente válida. Alguém pode esclarecer exatamente o que está acontecendo aqui?

Como uma nota lateral, no caso de alguém estar pesquisando como criar uma junção sem uma cláusula ON (como eu estava), você pode usar 'CROSS JOIN' para fazer isso, o que retorna o produto cartesiano. Kt Mack

Sua resposta

3   a resposta
5

há apenasINNER JOINs, a ordem deles não é realmente tão importante). Eu rearranjei sua consulta e agora se parece com isso:

SELECT TPM_TASK.TASKID 
FROM TPM_GROUP 
INNER JOIN TPM_USERGROUPS 
    ON TPM_GROUP.GROUPID = TPM_USERGROUPS.GROUPID 
INNER JOIN TPM_GROUPTASKS 
    ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID
INNER JOIN TPM_TASK
    ON TPM_TASK.TASKID = TPM_GROUPTASKS.TASKID 
INNER JOIN TPM_PROJECTVERSION 
    ON TPM_TASK.PROJECTID = TPM_PROJECTVERSION.PROJECTID 
    AND TPM_TASK.VERSIONID = TPM_PROJECTVERSION.VERSIONID 
INNER JOIN TPM_TASKSTAGE 
    ON TPM_TASK.STAGEID = TPM_TASKSTAGE.STAGEID 
INNER JOIN TPM_PROJECTSTAGE 
    ON TPM_PROJECTVERSION.STAGEID = TPM_PROJECTSTAGE.STAGEID 

Faz mais sentido para você agora ?, para mim.

20

intaxe ontem e fiquei um pouco desorientada.

Pelo visto,

FROM a 
     INNER JOIN b
     INNER JOIN c ON (b.id = c.id)
     ON (a.id = c.id)

é equivalente a uma subconsulta aninhada

FROM a
     INNER JOIN (SELECT <<list of columns>>
                   FROM b
                        INNER JOIN c ON (b.id=c.id)) c
             ON (a.id = c.id)
Sabe, eu tenho olhado isso há séculos e não consigo entender. Eu acho que minha confusão é em torno do uso dec como uma tabela e como um alias para a subconsulta. Isso é um erro de digitação ou uso típico? Neil Barnwell
@ NeilBarnwell - Não é um erro de digitação. Eu acredito que eu estruturei os aliases dessa maneira porquec na consulta original é usado como a tabela e, efetivamente, o alias para a subconsulta. Você poderia escrever a mesma coisa com a subconsulta com aliasd e a condição de junçãoa.id = d.id. Justin Cave
Ok, se esta sintaxe desconcertou a grande Justin Cave, então eu definitivamente não me sinto muito mal. Eu vou brincar com isso em algumas consultas mais simples, então eu entendo perfeitamente. Obrigado! Mike Christensen
Obrigado. Eu nem sabia que você poderia fazer isso, porque como ele saberia que você quis dizer o alias c, ou a tabela real c? Eu acho que há uma coisa de prioridade acontecendo, onde eu esperaria algum tipo de erro de referência ambíguo. Neil Barnwell
4

Ficaria bem se tivesse parênteses lá ...

SELECT TPM_TASK.TASKID 
FROM 
    TPM_GROUP 
    INNER JOIN TPM_USERGROUPS ON TPM_GROUP.GROUPID = TPM_USERGROUPS.GROUPID 
    INNER JOIN (
        TPM_TASK
        INNER JOIN TPM_GROUPTASKS ON TPM_TASK.TASKID = TPM_GROUPTASKS.TASKID 
        INNER JOIN TPM_PROJECTVERSION ON TPM_TASK.PROJECTID = TPM_PROJECTVERSION.PROJECTID 
            AND TPM_TASK.VERSIONID = TPM_PROJECTVERSION.VERSIONID 
        INNER JOIN TPM_TASKSTAGE ON TPM_TASK.STAGEID = TPM_TASKSTAGE.STAGEID 
        INNER JOIN TPM_PROJECTSTAGE ON TPM_PROJECTVERSION.STAGEID = TPM_PROJECTSTAGE.STAGEID 
    ) ON TPM_GROUP.GROUPID = TPM_GROUPTASKS.GROUPID

mas, como todas são íntimo, concordo com a resposta de Lamak.

Perguntas relacionadas