sábado, 6 de dezembro de 2008

SQL: Relacionamentos Self One-to-Many

Esses dias para o plano de contas do sistema, precisei criar um cadastro que funcionasse de forma hierarquica, onde cada cadastro obedecia uma sequência.

Exemplo
DESPESAS OPERACIONAIS
- ASSISTÊNCIA MÉDICA
- VALE TRANSPORTE
- ALIMENTAÇÃO
- PRO-LABORE
- SALÁRIOS


Note que os últimos 5 itens ficam dentro de um item de nível superior.
Nós podemos fazer isso usando duas tabelas e fazendo um relacionamento 1-N
ou, podemos criar um relacionamento chamado Self One-to-Many que utiliza a mesma tabela para poder fazer esses relacionamentos.

O SQL pode tratar uma mesma tabela de diferentes modos.


CRIANDO A TABELA

Iremos criar uma tabela bem simples de um cadastro de categorias para um restautante.
As categorias do restaurante costumam ser: Bebidas, Doces, Salgados....e dentro dessas categorias ou grupos, existem outros grupos que se encaixam como em Bebidas, eu posso ter: ÁGUAS, REFRIGERANTES, BEBIDAS ALCOÓLICAS, etc.

Para essa referência, criaremos um campo que funciona como chave estrangeira. É a mesma coisa como se fossemos criar uma outra tabela para fazer o relacionamento das categorias.

O Código para criação das tabelas para uma base MySQL, é a seguinte:

Create table `test`.`categorias`( `idcategoria` int(11) NOT NULL AUTO_INCREMENT , `idsubcategoria` int(11) , `nome` varchar(50) , PRIMARY KEY (`idcategoria`), KEY `FKcategoria` (`idsubcategoria`), CONSTRAINT `FKcategoria` FOREIGN KEY (`idsubcategoria`) REFERENCES `categorias` (`idcategoria`)) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;

Eu usei o tipo da tabela como INNODB, mas você poderá usar MyISAM normalmente.

Com a tabela criada, insira os dados na tabela como na imagem abaixo:


Veja que há um relacionamento de Refrigerantes, Alcoólicas e água com a categoria BEBIDAS.




CAPTURANDO DADOS RELACIONAMENTOS PELA MESMA TABELA


Para fazer a query e receber os dados relacionados, tratamos a tabela de categorias como 2 tabelas distintas relacionadas.

Para isso, podemos criar a seguinte query:
SELECT CONCAT(c.nome, ' >> ', s.nome) as categorias FROM categorias c, categorias s
WHERE s.idsubcategoria = c.idcategoria

O Concat serve para concatenar dados em uma query SQL.
O resultado será o seguinte:











Maravilha né?
Dessa forma, como utilizamos a mesma estrutura de dados para as tabelas, podemos fazer o relacionamento Self One-to-Many.

Qualquer dúvida, favor comentar ;)
Abraços...e até +

5 comentários:

Si disse...

Noooossa! Esse tutorial foi novidade pra mim, ainda não tinha visto nada do gênero! Muito legal!! Assim que precisar, vou usar com certeza! hahaha!

Si disse...

Mas em relação a performance, qual seria o mais recomendado? (1-N ou "Self to self"?)

Maurício Vinicius de O. Santos disse...

Com relação a performance, nao se ve quase diferença nenhuma mesmo quando a entidade possui muitas ocorrências.

Na realidade como se trata da mesma tabela, a performance acaba sendo melhor.

Esse tipo de JOIN é feito quando você precisa organizar os dados que terão as mesmas colunas. Costuma ser usado em tabelas com poucos atributos.
;)

Si disse...

ahh então tá certo.
Vou aplicar assim que precisar (e pelo jeito não vai demorar)! =)

Unknown disse...

Da hora a iniciativa do blog. Continue postando. Abraços!