Jump to content

POWERED BY:

Archived

This topic is now archived and is closed to further replies.

Regex

LEFT JOIN duas vezes na mesma tabela?

Recommended Posts

OLá pessoal,

 

Tenho uma tabela que é responsável pela associação de palavras que são sinônimos. Vejam:

CREATE TABLE `guia_sinonimos` (
  `sinonimo_id` int(11) NOT NULL AUTO_INCREMENT,
  `sinonimo_palavra1` int(11) NOT NULL,
  `sinonimo_palavra2` int(11) NOT NULL,
  PRIMARY KEY (`sinonimo_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

`sinonimo_palavra1` e `sinonimo_palavra2` fazem referência ao código de um campo da tabela guia_palavras.

 

Bem estou tentando exibir na tela os sinônimos da forma abaixo (uma palavra ao lado da outra):

 

carro - automóvel

moto - motocicleta

bicicleta - bike

etc...

 

 

O problema é que não sei como estruturar a query de modo que seja feito um JOIN para o campo 'sinonimo_palavra1' e outro para 'sinonimo_palavra2' (atribuição correta de variáveis).

 

Eu estava tentando desta forma:

 

"SELECT *, 
(SELECT * FROM guia_sinonimos LEFT JOIN guia_palavras ON palavra_id = sinonimo_palavra1) as p1, 
(SELECT * FROM guia_sinonimos LEFT JOIN guia_palavras ON palavra_id = sinonimo_palavra2) as p2 
FROM guia_sinonimos ORDER BY sinonimo_palavra1 ASC"

Entretanto sem sucesso (além da lógica estar errada, é retornado o erro "Operand should contain 1 column(s)", que eu sei que significa que foram retornados muitos resultados para uma só saída).

 

Enfim, busco ajuda dos amigos nesta resolução. Alguma idéia?

Share this post


Link to post
Share on other sites

beleza Regex? Posta a outra tabela pra ficar mais claro.

OPa, lá vai:

 

CREATE TABLE `guia_palavras` (
  `palavra_id` int(11) NOT NULL AUTO_INCREMENT,
  `palavra_palavra` varchar(25) NOT NULL,
	PRIMARY KEY (`palavra_id`)
) ENGINE=MyISAM AUTO_INCREMENT=37 DEFAULT CHARSET=latin1 AUTO_INCREMENT=37;

Share this post


Link to post
Share on other sites

Amigo, acho melhor você dar uma lida nesse material, do que eu te explicar.

 

Clique aqui para ler.

 

Se por acaso depois de ver os exemplos, você não conseguir, volte a postar que te dou uma força. http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

Share this post


Link to post
Share on other sites

Claudio,

 

Obrigado pela resposta, mas isto não resolve!

 

O problema (explicado de uma forma bem figurativa) é:

 

"FAÇA UMA JUNÇÃO COM A TABELA guia_palavras PARA DESCOBRIR QUAL É A PALAVRA COM O ID sinonimo_palavra1 e chame de p1, TAMBÉM FAÇA UMA JUNÇÃO COM A TABELA guia_palavras PARA DESCOBRIR QUAL É A PALAVRA COM O ID sinonimo_palavra2 e chame de p2".

Veja que o problema todo é o fato de sinonimo_palavra1 e sinonimo_palavra2 estarem na mesma tabela.

Quando a saída for dada, deverá ser impresso assim (PHP):

 

<? echo $row_resultado['p1']; ?> - <? echo $row_resultado['p2']; ?>

//isto deverá printar "bike - bicicleta", por exemplo.

Share this post


Link to post
Share on other sites

Olha, não sou "o cara" das LEFT JOIN's, mas tenta assim:

 

SELECT a.* FROM guia_sinonimos a
   LEFT JOIN guia_palavras b ON ( a.sinonimo_id = b.palavra.id )
Do pouco que eu sei e uso, vai selecionar todos os campos da tabela A (guia_sinonimos) cujos ID's baterem com o da tabela B (guia_palavras).

 

Você ainda pode, se necessário, condicionar com uma cláusula WHERE, para filtrar ainda mais.

 

Veja se te ajuda.

Share this post


Link to post
Share on other sites

Obrigado Imaggens,

 

mas veja que eu preciso de duas lefts joins em cima das duas mesmas tabelas, porém em atributos diferentes.

 

a sua query, como busca apenas uma vez, daria esse resultado:

 

carro - carro

bike - bike

 

Sendo que eu preciso de

 

carro - automóvel

bike - bicicleta

 

O problema é este, todos os nomes acima são provenientes do mesmo campo: palavra_palavra.......

Share this post


Link to post
Share on other sites

Hum... Olha, sinceramente com as suas tabelas não consegui muito.

 

Então, aproveitei que estou em um PC com MySQL e refiz a estrutura e, se eu entendi o propósito do tópico, consegui executar.

 

Query

SELECT p.* FROM palavras p 
   LEFT JOIN sinonimos s ON ( s.p_id = p.id ) WHERE s.sinonimo = "Carro"
A estrutura que montei deixei no RapidShare que, sem conta, limita a 10 downloads:

 

http://rapidshare.com/files/242714599/regex.sql..zip.html

 

Na tabela palavras, óbvio, você cadastra as palavras. E na de sinônimos, os sinônimos (dãã). Porém, na segunda tabela, tem um campo extra (p_id) onde você referencia a que palavra aquele sinônimo pertence.

 

Já populei um pouco pra testar.

 

Veja se te ajuda

Share this post


Link to post
Share on other sites

Imaggens,

 

obrigado pela resposta, mas infelizmente não consigo ver o arquivo porque moro em um condomínio e todos os computadores tem o mesmo IP (assim, sempre alguem já usou o IP no Rapidshare).

 

Envie por email por favor, para

seurolandolero[arroba]bol[ponto]com[ponto]br.

 

Grato

Share this post


Link to post
Share on other sites

Imaggens,

 

Muito obrigado pela ajuda, é uma boa solução! http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

Para este caso está OK, mas uso esta mesma lógica para outros problemas, como por exemplo uma nota fiscal que mostre dados do vendedor e do comprador, sendo que ambos estão na mesma tabela usuários...

 

Giesta,

 

Acredito que o caminho é este mesmo! Mas não consegui fazer a query gerar resultados, seguindo esta lógica.

 

O que são Z e X? São variáveis? E como exibo o resultado? Seria $row_resultado['z.id']?

Share this post


Link to post
Share on other sites

vou fazer um exemplo mais claro pra você....

 

 

select * from clientes c

LEFT JOIN devedores z ON z.cpf = c.cpf

LEFT JOIN devedores y ON y.rg = c.rg

 

assim eu fiz uma consulta que me tras todos os campos da tabela clientes (q eu chamei de c), e duas vezes (que uma vez eu chamei de z e na outra de y) todos os campos da tabela devedores, soh q na primeira juncao foi por cpf e na segunda por rg, pq as vezes eu tenho cpf mas nao tenho rg ou ao contrario

 

deu pra pegar?

Share this post


Link to post
Share on other sites

Sim giesta, obrigado!

 

Estamos no caminho! Mas os valores vem todos misturados.. Como exibo de forma individual? Ex:

 

<? echo $row_query['z.nome']; ?> - <? echo $row_query['y.nome']; ?>

 

(usar o "z." ou "y." não funciona aqui)...

 

Se por exemplo tenho uma nota fiscal com comprador e vendedor, ambos da tabelas pessoas, e quisesse exibir seus nomes lado a lado?

 

select * from pessoas p

LEFT JOIN notafiscal comp ON comp.cod = p.id

LEFT JOIN notafiscal vend ON vend.id = p.id

 

<? echo $row_query['comp.nome]; ?> - <? echo $row_query['vend.nome]; ?> Infelizmente não funciona...

Share this post


Link to post
Share on other sites

Sim giesta, obrigado!

 

Estamos no caminho! Mas os valores vem todos misturados.. Como exibo de forma individual? Ex:

 

<? echo $row_query['z.nome']; ?> - <? echo $row_query['y.nome']; ?>

 

(usar o "z." ou "y." não funciona aqui)...

Regex, no exemplo acima, a tabela clientes ganhou o pseudônimo "c". Isso permite, ao selecionar os dados desejados, utilizar c.cpf e/ou c.rg ao invés de clientes.cpf.

O mesmo acontece com a tabela devedores. Mas na hora de exibir na página, você só precisa colocar assim: $row_query['nome']; ao invés de $row_query['z.nome'];

 

Se conseguiu entender, favor postar aqui.

Share this post


Link to post
Share on other sites

Claudio, obrigado, isto eu entendi!

 

Vamos a um exemplo simples e prático para facilitar. Dadas as tabelas:

 

Cadastro de pessoas (vendedores e compradores)

CREATE TABLE `pessoa` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nome` varchar(25) NOT NULL,
  PRIMARY KEY (`id`)
) 

INSERT INTO `pessoa` (`id`, `nome`) VALUES (1, 'João');
INSERT INTO `pessoa` (`id`, `nome`) VALUES (2, 'Jorge');
INSERT INTO `pessoa` (`id`, `nome`) VALUES (3, 'Maria');
INSERT INTO `pessoa` (`id`, `nome`) VALUES (4, 'Pedro');

Notas fiscais

 

CREATE TABLE `notafiscal` (
  `cod` int(11) NOT NULL AUTO_INCREMENT,
  `vendedor` int(11) NOT NULL,
  `comprador` int(11) NOT NULL,
  `produto` varchar(25) NOT NULL,
  PRIMARY KEY (`cod`)
) 

INSERT INTO `notafiscal` VALUES (1, 1, 3, 'rádio');
INSERT INTO `notafiscal` VALUES (2, 1, 2, 'skate');

E eu quisesse retornar o resultado da seguinte maneira (leitura da primeira notafiscal):

 

Nota Fiscal nº 1

Vendedor: João

Comprador: Maria

Produto: rádio

 

A pergunta que não quer calar é: como seria estruturada a query, para que o banco entenda que são duas pessoas distintas?

Share this post


Link to post
Share on other sites

Cara, daquele jeito eu não consegui, mas se achar que esse exemplo te ajuda... observe abaixo:

 

CREATE TABLE `notafiscal` (
 `cod` int(11) NOT NULL AUTO_INCREMENT,
 `vendedor` int(11) NOT NULL,
 `comprador` int(11) NOT NULL,
 `produto` int(11) NOT NULL,
 PRIMARY KEY (`cod`)
) 

INSERT INTO `notafiscal` (`cod`, `vendedor`, `comprador`, `produto`) VALUES
(1, 1, 3, 1),
(2, 4, 2, 2);

CREATE TABLE  `pessoa` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `nome` varchar(25) NOT NULL,
 PRIMARY KEY (`id`)
)

INSERT INTO `pessoa` (`id`, `nome`) VALUES
(1, 'João'),
(2, 'Jorge'),
(3, 'Maria'),
(4, 'Pedro');

-- --------------------------------------------------------

CREATE TABLE `produto` (
 `produto_id` int(11) NOT NULL AUTO_INCREMENT,
 `produto_nome` varchar(25) NOT NULL,
 `nome_vendedor` varchar(100) NOT NULL,
 PRIMARY KEY (`produto_id`)
)

INSERT INTO `produto` (`produto_id`, `produto_nome`, `nome_vendedor`) VALUES
(1, 'skate', 'João'),
(2, 'bike', 'Pedro');

 

E para a consulta:

SELECT *  FROM notafiscal AS n LEFT JOIN produto AS p ON p.produto_id = n.produto LEFT JOIN pessoa AS v ON v.id = n.vendedor LEFT JOIN pessoa AS c ON c.id = n.comprador ORDER BY n.cod DESC;

 

Da forma que está o primeiro resultado será:

Nota fiscal n° 2

Vendedor: Pedro

Comprador: Jorge

Produto: bike

Se for isso o que você quer... assim acho que já quebra um galho. Posta aí se serviu, ok? http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

Share this post


Link to post
Share on other sites

×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.