Inner Join em Tabela N:N

1,215 views
Skip to first unread message

Klassikys

unread,
Dec 8, 2011, 2:03:25 PM12/8/11
to PHP MG
Galera, preciso de uma ajuda.

Tenho 3 tabelas: tab_produto, tab_fornecedor e tab_prod_for

tab_produto
- id
- nome
- preco

tab_fornecedor
- id
- nome

tab_prod_for
- id_produto
- id_fornecedor

Como eu quero poder adicionar varios fornecedores para o mesmo
produto, tive q criar uma tabela N:N (tab_prod_for)

O que eu quero saber é como puxar por exemplo o nome dos produtos com
seus fornecedores.
Ex: Teclado - Kalunga e Microsoft

Seria com INNER JOIN? Como?

Alex C. Souza

unread,
Dec 9, 2011, 5:22:32 AM12/9/11
to ph...@googlegroups.com
SELECT p.nome as nome_produto, f.nome as nome_fornecedor FROM tab_produto p
INNER JOIN tab_prod_for pf ON pf.id_produto = p.id
INNER JOIN tab_fornecedor f ON pf.id_fornecedor = f.id

Fazendo esta consulta, você obterá uma lista com cada variação entre nome do produto e nome do fornecedor... ou seja, de acordo com seu exemplo:

nome_produto | nome_fornecedor

Teclado          |  Kalunga
Teclado          |  Microsoft
Teclado          |  Loja1
Mouse            | Kalunga
Mouse            | Loja2

Ai com PHP vc trata as repetições de nome de produto e concatena os fornecedores... é a maneira mais indicada, eu acho... há uma outra forma (que já usei muito mas pode causar problemas):

SELECT p.nome as nome_produto, GROUP_CONCAT(f.nome SEPARATOR ", ") as nome_fornecedor FROM tab_produto p
INNER JOIN tab_prod_for pf ON pf.id_produto = p.id
INNER JOIN tab_fornecedor f ON pf.id_fornecedor = f.id
GROUP BY nome_produto

Essa cláusula efetuará a mesma consulta, porém concatenará os nomes de fornecedores usando ", " como separador e totalizará por nome do produto (pode tornar a consulta mais lenta, mas evita processamento pelo PHP), por exemplo:

nome_produto | nome_fornecedor

Teclado          |  Kalunga, Microsoft, Loja1
Mouse            | Kalunga, Loja2

Um outro problema para esta última forma é que  group_concat_max_len,
que é uma configuração do MySQL, indica o tamanho máximo para concatenação, então se um produto possui uma lista muito extensa de fornecedores, o resultado poderá ser truncado. O valor "default" para essa configuração é 1024. Você pode alternativamente, alterar esta configuração através da query:

SET SESSION group_concat_max_len = 2048;
(para configuração somente para a conexão aberta)
ou

SET GLOBAL group_concat_max_len = 2048;
(para configuração permanente até que o mysql seja reiniciado)

Pra entender melhor o uso de GROUP_CONCAT(), da uma olhada no link:

Lá tem mais informações sobre a configuração da variável group_concat_max_len também.

Aconselharia utilizar a primeira forma, a não ser que tenha absoluta certeza de que a segunda forma será mais vantajosa. Espero ter ajudado.


--
Você recebeu esta mensagem porque está inscrito no grupo "PHP MG" no grupos do Google.
 Site oficial do grupo: http://www.phpmg.com
 Para postar neste grupo, envie um e-mail para ph...@googlegroups.com
 Para cancelar a sua inscrição neste grupo, envie um e-mail para phpmg-un...@googlegroups.com
 Regras da lista: http://groups.google.com/group/phpmg/web/regras-da-lista
 Para ver mais opções, acesse http://groups.google.com/group/phpmg



--
/*-----------------------------
Alex C. Souza
Desenvolvedor Web
31 8539 8683
-----------------------------*/

Ítallo Costa

unread,
Dec 9, 2011, 6:14:57 AM12/9/11
to ph...@googlegroups.com


SELECT p.nome as produto , f.nome as fornecedor
FROM tab_produto p

   JOIN tab_prod_for pf   ON pf.id_produto = p.id
   JOIN tab_fornecedor f ON f.id               =  pf.id_fornecedor
ORDER  BY p.nome

Se você for trazer todo mundo de uma vez o melhor é desse jeito.

Agora se for em uma tela de cadastro eu faria duas consultas.

Não sei se o grupo concorda, mas eu faria assim

Em 8 de dezembro de 2011 17:03, Klassikys <klassik...@gmail.com> escreveu:

Weslley Alves

unread,
Dec 8, 2011, 5:03:40 PM12/8/11
to ph...@googlegroups.com
Klassikys, pelo que entendo isso seria sim um INNER JOIN, segue esse abaixo:

SELECT * 
FROM tb_produto AS Produto
INNER JOIN tab_prod_for AS ProdForn ON ( Produto.id = ProdForn.id_produto ) 
INNER JOIN tb_fornecedor AS Fornecedor ON ( ProdForn.id_fornecedor = Fornecedor.id ) 

Klassikys.

Alex C. Souza

unread,
Dec 10, 2011, 9:52:52 AM12/10/11
to ph...@googlegroups.com
Ítalo, no Mysql, se você usar somente JOIN, a junção será feita como INNER JOIN, portanto tanto faz utilizar o INNER JOIN ou somente JOIN... então eu diria que também concordo com o seu modo... assim como também concordo com a forma em que o Weslley adicionou (ele ainda utilizou parênteses, o que torna o SQL mais elegante, ehehehe)... 



--
Você recebeu esta mensagem porque está inscrito no grupo "PHP MG" no grupos do Google.
Site oficial do grupo: http://www.phpmg.com
Para postar neste grupo, envie um e-mail para ph...@googlegroups.com
Para cancelar a sua inscrição neste grupo, envie um e-mail para phpmg-un...@googlegroups.com
Regras da lista: http://groups.google.com/group/phpmg/web/regras-da-lista
Para ver mais opções, acesse http://groups.google.com/group/phpmg
Reply all
Reply to author
Forward
0 new messages