Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Fiz algumas pesquisas e testes sobre "self join", porém ainda não consegui fazer o que eu gostaria, acredito que seja uma dúvida clássica isso já, porém não estou conseguindo resolver. Vou dar um exemplo.
Minha dúvida é ref. a Categorias e Subcategorias. A estrutura básica que tenho da tabela Categorias é a seguinte:
id_categoria
id_categoria_pai (referenciando essa mesma tabela, campo null)
nome
descricao
ativo
Certo?
Outra tabela é por exemplo, Produtos:
id_produto
id_categoria (fk_tbl_categorias, not null)
nome
descricao
ativo
Fiz esse exemplo simples, porém acredito que deve servir para vários outros exemplos que utilizam subcategorias (Se não for, me corrija).
Minha dúvida é, como posso fazer um SELECT entre essas duas tabelas, onde irei ter os campos: nome da categoria e nome também da subcategoria juntamente com o nome do produto e outras informações que eu achar pertinente. Como consigo fazer isso?
Lembrando que o produto pode ou não ter subcategoria, mas a categoria é obrigatório ter. Valeu...
http://dba.stackexchange.com/questions/46127/recursive-self-joins
Hierarchical queries, as those recursive queries are known, are not supported for MySQL.
Se você utilizar o PHP, poderá iniciar a consulta pelo topo:
'[...] WHERE id_categoria_pai IS NULL;'
E, pelo PHP, continuar a busca através dos níveis:
$statementSub = $pdo->prepare('SELECT * FROM categorias WHERE id_categoria_pai = :id_categoria_pai;');
foreach($statement AS $row) {
$statementSub->bindParam(':id_categoria_pai' , $row['id_categoria']);
$statementSub->execute();
/** mais códigos **/
}
Esse trecho de código, acima, irá ajudar a buscar a categoria filha. Após, é só criar a recursividade, e você poderá ter N níveis de categoria.
Olha só, minhas tabelas são essas:
/applications/core/interface/imageproxy/imageproxy.php?img=http://s32.postimg.org/ve677v8g5/Screen_Hunter_15_May_20_10_44.png&key=c5410a8cbf08ac17c774289e8a9bb68344b2f862e2376a9aba197eb82e10c7d6" alt="Screen_Hunter_15_May_20_10_44.png" />
Até aí acredito que a modelagem esteja ok, certo?
Aí no resultado eu gostaria de buscar os seguintes campos:
/applications/core/interface/imageproxy/imageproxy.php?img=http://s32.postimg.org/vnskzzzwl/Screen_Hunter_15_May_20_10_47.png&key=00f7a0cab07cd2b5d943ca736d34f34c29c0eb6a6403ec7864f865381c6bda6b" alt="Screen_Hunter_15_May_20_10_47.png" />
Até consegui fazer essa busca, porém com resultados repetidos e onde é o categoria ele pega o nome da subcategoria caso o cadastro tenha uma, usei o seguinte código:
SELECT
m.id_manual, m.titulo, m.arquivo, m.downloads, cat.id_categoria, cat.id_subcategoria, cat.categoria, cat.subcategoria
FROM
nw_manuais_tecnicos m
LEFT JOIN
(SELECT
cp.id_categoria, cf.id_categoria_pai id_subcategoria,
cp.nome categoria, cf.nome subcategoria
FROM
nw_manuais_tecnicos_categorias cp
LEFT JOIN
nw_manuais_tecnicos_categorias cf
ON
cp.id_categoria=cf.id_categoria_pai
) cat
ON
m.id_categoria=cat.id_categoria
Até estou fazendo a junção das duas tabelas, porém os campos não estão ficando certos, o que eu gostaria é que no campo categoria, ficasse o nome da categoria e caso tenha subcategoria o nome da subcategoria ficasse no campo subcategoria, consequentemente isso para os campos id_categoria e id_subcategoria.
Como eu poderia fazer isso? ou comente filtrando com PHP?
Gostaria de fazer somente uma Query pra isso se for possível.
Alguém da uma luz? :rolleyes:
É mais confiável você utilizar uma consulta linear, que busque o topo da lista (ou base da árvore) e, utilizando o PHP, comece a iterar sobre os nodes. Pois somente com SQL (MySQL no caso) a quantidade de níveis ficará dependente do quanto você implementar com o SQL.
Outro ponto, você está montando a estrutura em árvore à partir do fim para o início, isso pode estar causando a duplicação. Sempre "comece do começo". Em uma estrutura em árvore, é a base.
Eu sugeriria montar a estrutura realizando as consultas e organizando os dados no PHP.
Pois somente com SQL, você possuirá uma estrutura em SQL muito engessada.
>
É mais confiável você utilizar uma consulta linear, que busque o topo da lista (ou base da árvore) e, utilizando o PHP, comece a iterar sobre os nodes. Pois somente com SQL (MySQL no caso) a quantidade de níveis ficará dependente do quanto você implementar com o SQL.
Outro ponto, você está montando a estrutura em árvore à partir do fim para o início, isso pode estar causando a duplicação. Sempre "comece do começo". Em uma estrutura em árvore, é a base.
Eu sugeriria montar a estrutura realizando as consultas e organizando os dados no PHP.
Pois somente com SQL, você possuirá uma estrutura em SQL muito engessada.
Em termos de modelagem das tabelas, está correto ou teria algum ajuste?
A modelagem está ok. A implementação que deve ser reformulada.
A modelagem está ok. A implementação que deve ser reformulada.
Teria algum código em php de exemplo a ser seguido?
Também da pra usar uma só tabela pra listar essa hierarquia de categorias.
De uma olhada!
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
Esta é a lógica mais simples
https://phptechnologytutorials.wordpress.com/2014/12/14/recursive-category-tree-in-php-and-mysql/
Tem bastante exemplo na net sobre JOIN.
Mas basicamente para fazer a ligação você precisa verificar se a tabela é do mesmo tipo primitivo.
INT 'deveria' ser INT, varchar deve ser varchar e assim por diante....
Vamos criar um banco aqui só de zoas como exemplo.
OK... agora temos um banco com 2 tabelas.
Se por exemplo listarmos todas as profissões rola esse result:
mysql> SELECT * FROM PROFISSAO;
+----+-------------+
| id | nome |
+----+-------------+
| 1 | Programador |
| 2 | Jedi |
| 3 | Gravatinha |
| 4 | Dev PL/SQL |
| 5 | DBA |
+----+-------------+
Bacana... se listarmos todos as pessoas:
mysql> select * from pessoa;
+----+--------+--------------+
| id | nome | profissao_id |
+----+--------+--------------+
| 1 | Joao | 1 |
| 2 | Anakin | 2 |
| 3 | Sergio | 3 |
| 4 | Yoda | 2 |
+----+--------+--------------+
Ai é que está o lance do relacionamento no caso queremos trazer o resultado do nome na profissao_id.
Vamos pegar o Yoda ... pq o Yoda é mestre HSAUHASUSA
/Exemplo 1: /
FROM
pessoa
LEFT OUTER JOIN profissao ON(
pessoa.profissao_id = profissao.id
)
WHERE pessoa.id = 4;
+----+------+----------------+
| id | nome | profissao_nome |
+----+------+----------------+
| 4 | Yoda | Jedi |
+----+------+----------------+
...
LEFT OUTER JOIN profissao ON(
pessoa.profissao_id = profissao.id
)
Neste trecho ele liga todos os resultados com a tabela e assim podemos especificar ela no SELECT.
Banco de dados é viagem,
Outro exemplo só pra tentar deixar mais claro como ele funciona (ou embananar mais sua cabeça haha)
Podemos também trazer todos os resultados e 'refinar' dentro do Where (oq não deixa muito legível)
Ex:
/Exemplo 2: /
FROM
pessoa, profissao
WHERE
pessoa.profissao_id = profissao.id
AND pessoa.id = 4
;
De qlq forma prefira sempre ao fazer Joins o exemplo 1.
Se tu curtir ir mais na parte teórica da parada vale a pena dar uma lida:
https://pt.wikipedia.org/wiki/Diagrama_de_Venn
No HackerRank tem uma porrada de exercicios pra quem ta começando SQL, vale a pena conferir tmb:
https://www.hackerrank.com/