• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Bjecas

[SQL] Ai valham-me os JOIN...

9 mensagens neste tópico

Boas pessoal!

Estou a precisar de alguma ajuda, o problema é o seguinte:

A tabela1 tem os dados dos utilizadores (id, username, e mais coisas), a tabela2 tem mensagens privadas (mensagem_id, remetende_id, destinatario_id, e mais coisas). Agora, precisava de ir buscar o tabela1.username correspondente ao tabela2.remetente_id, e ainda o tabela1.username correspondente ao tabela2.destinatario_id (além do resto das coisas da tabela2).

Alguem pode me ajudar?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

select *
  from tabela1, tabela2
  where tabela1.username = tabela2.remetente_id

select *
  from tabela1, tabela2
  where tabela1.username = tabela2.destinatario_id

também podias usar JOINs, mas assim escreve-se menos :thumbsup:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

JÁ SEI! Quer dizer, pelo menos parece que está a resultar. Simplificar as coisas para colocá-las aqui no fórum ajudou bastante!

SELECT destinatario_id, join1.username AS destinatario_nome, remetente_id, join2.username AS remetente_nome
FROM tabela2 
LEFT JOIN tabela1 AS join1 ON tabela2.destinatario_id = join1.id
LEFT JOIN tabela1 AS join2 ON tabela2.remetente_id = join2.id

Vendo o código até nem parece complicado, mas nem sabia que dava para juntar a mesma tabela duas vezes, em sítios diferentes... Viva os alias!

Se alguém souber uma maneira mais eficiente de resolver o problema, é muito bem-vinda  :thumbsup:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

não sei exactamente qual é o teu objectivo, mas fazer LEFT JOINs nem sempre é boa ideia, pois isso pode-te meter nulls no resultado...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

não sei exactamente qual é o teu objectivo, mas fazer LEFT JOINs nem sempre é boa ideia, pois isso pode-te meter nulls no resultado...

O objectivo é seleccionar quase tudo da tabela 2 (a que fica à esquerda do join, por isso não há crise), e apenas 2 campos das tabelas à direita (um campo em cada tabela) que de certeza não ficam vão ficar vazios. Mas obrigado pelo aviso, se me começarem a aparecer NULLs no futuro já sei :P

Explicando de outra maneira: tenho uma tabela onde guardo os utilizadores (id e username), e outra com mensagens. Na tabela das mensagens tenho os IDs do remetente e destinatário, mas para mostrar o username em vez do ID tenho que fazer um join com a tabela de utilizadores. Como tenho que saber usernames para remetente e destinatário, tenho que fazer dois joins.

Acho que é assim, porque pelo menos funciona :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

se a tabela da esquerda forem as mensagens, como todas as mensagens devem ter um utilizador, não há problema.

se a tabela da esquerda forem os utilizadores, caso algum não tenha mensagem, podes ter problemas.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

se a tabela da esquerda forem as mensagens, como todas as mensagens devem ter um utilizador, não há problema.

se a tabela da esquerda forem os utilizadores, caso algum não tenha mensagem, podes ter problemas.

Hipótese 1 :P

Já agora, será que há alguma maneira mais eficiente de resolver o problema?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Basicamente o mesmo mas sem JOIN:

select destinatario_id, T1.username AS destinatario_nome, remetente_id, T2.username AS remetente_nome
from tabela1 T1, tabela1 T2, tabela2 T3
where T1.id = T3.destinatario_id
and T2.id = T3.remetente_id

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O objectivo é seleccionar quase tudo da tabela 2 (a que fica à esquerda do join, por isso não há crise), e apenas 2 campos das tabelas à direita (um campo em cada tabela) que de certeza não ficam vão ficar vazios. Mas obrigado pelo aviso, se me começarem a aparecer NULLs no futuro já sei ;)

Os LEFT JOIN (e RIGHT JOIN, que vai dar ao mesmo), são usados para juntar duas tabelas em que queres resultados da tabela da esquerda *mesmo* que na da direita não haja um registo equivalente. O JOIN (ou INNER JOIN) só te devolve registos da esquerda se na da direita houver registos equivalentes (e daí o left join poder devolver campos nulos)

Explicando de outra maneira: tenho uma tabela onde guardo os utilizadores (id e username), e outra com mensagens. Na tabela das mensagens tenho os IDs do remetente e destinatário, mas para mostrar o username em vez do ID tenho que fazer um join com a tabela de utilizadores. Como tenho que saber usernames para remetente e destinatário, tenho que fazer dois joins.

Acho que é assim, porque pelo menos funciona :P

Ora bien, assumindo que:

- a tabela de mensagens se chama mensagem, e tem dois campos remetente_id e destinario_id, bem como um campo de texto;

- a tabela de utilizadores se chama utilizador e tem campos id e username

select 
remetente.id as remetente_id, 
remetente.username as remetente_username, 
destinatario.id as destinatario_id, 
destinatario.username as destinatario_username,
mensagem.id,
mensagem.texto
from 
mensagem 
inner join utilizador remetente on mensagem.remetente_id = remetente.id
inner join utilizador destinatario on mensagem.destinatario_id = destinatario.id

isto é equivalente a dizer:

select 
remetente.id as remetente_id, 
remetente.username as remetente_username, 
destinatario.id as destinatario_id, 
destinatario.username as destinatario_username,
mensagem.id,
mensagem.texto
from 
mensagem, utilizador remetente, utilizador destinatario
where
mensagem.remetente_id = remetente.id and
mensagem.destinatario_id = destinatario.id

A BD é simpática o suficiente para optimizar a query com where numa query com join, pelo que vai dar mais ou menos ao mesmo.

Substituindo inner joins por left outer joins faria com que todos os registos da tabela de mensagens fossem devolvidos, inclusive aqueles que têm remetente_id e/ou destinatario_id vazios + os que tenham esses campos preenchidos mas sem correspondência na tabela de utilizadores. Nestes casos, os campos de ids sem correspondência na tabela de utilizadores viriam a NULL.

A utilidade do left outer join é para outros casos, por exemplo, se quiseres ir buscar todos os utilizadores e *opcionalmente* as mensagens que eles tenham numa só query (podem ser 0 ou mais mensagens).

shana

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora