Agrupamento na mesma tabela usando indices

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

chrissoares
Usuário Nível 1
Usuário Nível 1
Mensagens: 45
Registrado em: 23 Dez 2009 14:35
Localização: Belo Horizonte/MG
Contato:

Agrupamento na mesma tabela usando indices

Mensagem por chrissoares »

Saudações a todos!

Gostaria de compartilhar uma necessidade e quem sabe conseguir uma ideia diferente das que tenho.
Estou criando, em um sistema, um cadastro de categorias com subcategorias.
Inicialmente pensei em usar duas tabelas, uma Principal para as categorias e uma tabela secundária para as subcategorias, mas desta forma o número de níveis estaria relacionado com o número de tabelas, o que complicaria muito.
Resultado seria semelhante a isto:

Código: Selecionar todos

Categoria
-----------
Software
Livro
Subcat1
---------
Gratuito
Pago
Demonstração
Romance
Auto Ajuda
Subcat2
---------
Imagem
Editor de Texto
Desenvolvimento
Ao montar uma consulta, iria fazer os relacionamentos da maneira que ao selecionar uma Categoria apareceriam as subcategorias relacionadas.

Pensei novamente e se replicar na tabela categoria as subcategoria e criar um campo na tabela de categoria, onde digo que ela é uma categoria subcategoria e vai possuir outras subcategorias.

Código: Selecionar todos

Categoria
-----------
Software
Livro
Gratuito - Sub 
Pago - Sub
Demonstracao - Sub
Romance - Sub
Auto Ajuda - Sub
Subcat
--------
Gratuito
Pago
Demonstracao
Romance 
Auto Ajuda
Imagem
Editor de Texto
Desenvolvimento
Desta forma poderia ter várias quebras mantendo apenas o uso de duas tabelas.

Mas continuei imaginando e utilizando uma tabela que relacione com ela mesma, também conseguiria fazer algo semelhante. Porém não consegui pensar em formas de fazer, cheguei a fazer alguns testes com índices, mas não deu certo, ficaram as categorias juntas, em seguida as subcategorias do primeiro nível, depois do segundo e assim por diante.
Quero que fique no estilo de Arvore de Diretórios. Se alguém tiver alguma ideia eu aceito!

Vou continuar pensando e vou postando a medida que estiver trabalhando nela.

Obrigado e abraços a todos!
Christiano R. Soares
Analista Desenvolvedor
www.bhdados.com.br

'Tudo o que fizerem, façam de todo o coração, como para o Senhor, e não para os homens, sabendo que receberão do Senhor a recompensa da herança. É a Cristo, o Senhor, que vocês estão servindo. '
Colossenses 3:23-24
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Agrupamento na mesma tabela usando indices

Mensagem por Eolo »

Uma solução pode ser parametrizar os registros do seu DB.
Exemplo:

campoA - FORMATO
- "00" não importa
- "01" digital
- "02" papel

campoB - PREÇO
- "00" não importa
- "01" gratuito
- "02" gratuito para teste
- "03" caro demais
- "99" padrão FIFA

campoC - AUTOR
- "00" não importa
- "01" brasileiro
- "02" alemão
- "03" chinês

campoD - NOME DO AUTOR
- "00000" não importa
- "00001" José Silva
- "00002" Hong Chi Li
- "00003" Frederick von Kultz

Crie um índice concatenando os quatro campos:
INDE ON campoa+campob+campoc+campod

Na hora de procurar por exemplo livros no formato PAPEL, de qualquer preço, do autor chinês de nome Hong Chi Li:
SEEK "02000300002"

Sacou a idéia?
Vamos ver se resolve, qualquer coisa buzina.
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Agrupamento na mesma tabela usando indices

Mensagem por Eolo »

Tem também a função OrdWildSeek(), fantástica.
Mas o enfoque, no DB, seria um pouco diferente.

Veja se a outra idéia resolve, senão vamos falar do OrdWildSeek().
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Agrupamento na mesma tabela usando indices

Mensagem por JoséQuintas »

Em termos de código, pra ordem de código, poderia ser código composto:

000001 - categoria
000001.000001 - subcategoria da categoria 000001


Ou deixar livre:

categoria - 000001
subcategoria - 000001

livros
categoria 000001
subcategoria 000001

Ao listar o cadastro de livros, listar por categoria + subcategoria

Opcionalmente, pode ter uma função pra retornar a descrição, para o caso de ordem alfabética por exemplo.

index on Categoria( código ) + subcategoria( CodSub ) + nome to temp

E na seleção de subcategoria, só mostrar o que começa com o código da categoria.

Talvez arquivos separados facilitem o controle.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Agrupamento na mesma tabela usando indices

Mensagem por Eolo »

José Quintas, não entendi direito o que vc acrescentou.
Sério, tentei entender o q vc postou, não consegui.

Vc disse "poderia ser código composto". O que isso difere do que falei?

Posta um exemplo aí pra gente entender.Tem jeito?
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Agrupamento na mesma tabela usando indices

Mensagem por JoséQuintas »

No mesmo banco de dados, no cadastro de códigos, a primeira parte seria categoria e a segunda parte a subcategoria
Pra simplificar usando código menor:
o primeiro código seria 001 ou 001.000
o segundo código seria 001.001, a subdivisão do 001.
No cadastro que vai usar categoria/subcategoria, usaria o código da subcategoria.
livro, subcategoria 001.001

Caso sejam arquivos separados, ficaria igual o seu, mas teria que digitar os dois códigos no cadastro principal.
livro, categoria 001 e subcategoria 001
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Agrupamento na mesma tabela usando indices

Mensagem por Eolo »

Na hora de procurar por exemplo livros no formato PAPEL, de qualquer preço, do autor chinês de nome Hong Chi Li:
SEEK "02000300002"
Juro que ainda não saquei...

Talvez a diferença seja que, no meu exemplo, não coloquei pontos, porque não precisa. Mas seria algo assim, "02.00.03.00002", semelhante ao que vc postou.

Outra diferença: vc setou categoria e sub-categoria. Bem, eu imaginei algo sem limite, como num plano de contas (contábil). Pode ter categoria, sub-cat, sub-sub-cat, sub-sub-sub... Aí, se eu quiser selecionar algo definido no "15o. sub-sub", sem me importar com os 14 anteriores, basta colocar "00" neles...

Tenho um sistema de vídeo locadora (nem sei se ainda tá rodando no cliente), podia-se pesquisar por uma dezena de filtros. Exemplo: "aniversário da Audrey Hepburn? Vamos conferir todos os filmes que temos dela, mas só aqueles em que o diretor foi o Fulano, filmados entre data1 e data2...".

Era Summer 87, Plink86, NTX, SEEK. Pensa num trem véio... :-)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Agrupamento na mesma tabela usando indices

Mensagem por JoséQuintas »

Postei duas formas diferentes.
Na primeira, um único arquivo contém toda classificação, e o cadastro utiliza um único código.
Na segunda, cada arquivo contém uma das classificações, e o cadastro vai utilizar vários códigos.
Sendo assim, não dá pra duas formas diferentes serem iguais à sua.

A pergunta foi sobre usar uma única tabela com as classificações, então seria a primeira forma.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
chrissoares
Usuário Nível 1
Usuário Nível 1
Mensagens: 45
Registrado em: 23 Dez 2009 14:35
Localização: Belo Horizonte/MG
Contato:

Agrupamento na mesma tabela usando indices

Mensagem por chrissoares »

Eolo e José Quintas, quero lhes agradecer muito pelas ideias que me deram.

São grandes soluções para o meu problema e vou estar utilizando-ás, obrigado!

Eolo, andei pesquisando sobre o OrdWildSeek(), não consegui fazer o seu uso correto, mas vou seguir este caminho também, pois será mais fácil para os usuários encontrarem as categorias e pretendo utiliza-lo nas minhas pesquisas em geral.

Caso alguém queira uma ideia um pouco complexa mas muito interessante, pesquise sobre o Nested set model um modelo de conjuntos aninhados. Cheguei a ele pesquisando as Categorias de Artigos utilizada no Joomla, elas funcionam apenas com uma tabela, e são montadas em uma estrutura tipo arvore. Em um outro momento vou tentar montar uma categoria parecida.

Obrigado mais uma vez Eolo e José Quintas!
Vou começar a utilizar o OrdWildSeek(), existe algum detalhe a ser feito nas tabelas ? Meu sistema utiliza o DBF/DBT com NTX.

Abraços!
Christiano R. Soares
Analista Desenvolvedor
www.bhdados.com.br

'Tudo o que fizerem, façam de todo o coração, como para o Senhor, e não para os homens, sabendo que receberão do Senhor a recompensa da herança. É a Cristo, o Senhor, que vocês estão servindo. '
Colossenses 3:23-24
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Agrupamento na mesma tabela usando indices

Mensagem por Eolo »

O OrdWildSeek() é uma "mistura" de SEEK e LOCATE.

O SEEK só acha o registro cujo INÍCIO coincida com o que vc está procurando. Se vc tem o registro "JOSE JOAQUIM" e fizer SEEK "OAQUIM", o SEEK não vai achar nada. E exite o LOCATE, que acha o "OAQUIM" do exemplo, mas demora demais... O OrdWildSeek() acha o "OAQUIM" como o LOCATE e é instantâneo como o SEEK.

Por exemplo, vc tem um DB de nomes de cosméticos e quer selecionar só os itens que contenham "CASP", não importa ONDE essa string esteja dentro do registro. Esses registros são os seguintes:

recno() - EAN8 - CAMPO1
1345 - 78812981 - SHAMPOO ANTI CASPA MORTEX
128983 - 79928122 - CREME ANTI-CASPA CAIU TUDO
782 - 79280002 - SHAMPU ANTICASPA NEVE

Código: Selecionar todos

use arquivo
set inde on campo1 to arquivo
set orde to 1
go top
procura="CASP"
nomes={}
a=1
do whil OrdWildSeek("*"+alltrim(procura)+"*",iif(a=1,.f.,.t.))
  aadd(nomes,campo1+" "+str(ean8,0))
  a++
  if a>200
    * passou de 200 registros...
    * precisa colocar um limite, porque imagina se o usuario manda procurar a letra "A"...
    * eu uso o seguinte: a procura tem que ter no mínimo 5 caracteres
    exit
  endi
endd
if len(nomes()=0
  * não achou nada
else
  * a matriz NOMES vai ter 3 registros, conforme acima
endi
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Agrupamento na mesma tabela usando indices

Mensagem por Eolo »

Vou começar a utilizar o OrdWildSeek(), existe algum detalhe a ser feito nas tabelas ? Meu sistema utiliza o DBF/DBT com NTX.
Eu uso o CDX e não sei dizer se funciona igual com o NTX.

Não precisa alterar nada nos DBF, basta que o campo (fonte da procura) esteja indexado.

Aliás, dá pra usar "curingas" também. Por ex, "*EL" procura por todos nomes, de qualquer tamanho, que terminem com "EL". Já "??EL" procura palavras com 4 letras que terminem com "EL".
chrissoares
Usuário Nível 1
Usuário Nível 1
Mensagens: 45
Registrado em: 23 Dez 2009 14:35
Localização: Belo Horizonte/MG
Contato:

Agrupamento na mesma tabela usando indices

Mensagem por chrissoares »

Obrigado Eolo.

Entendi como funciona, agora vou começar a colocá-lo no meu sistema.

Pelo que vi, não poderia simplesmente trocar onde utilizo o dbSeek(), tem a questão de informar apenas uma unica letra, por exemplo.

Muito obrigado!

Abraços!
Christiano R. Soares
Analista Desenvolvedor
www.bhdados.com.br

'Tudo o que fizerem, façam de todo o coração, como para o Senhor, e não para os homens, sabendo que receberão do Senhor a recompensa da herança. É a Cristo, o Senhor, que vocês estão servindo. '
Colossenses 3:23-24
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Agrupamento na mesma tabela usando indices

Mensagem por Eolo »

Pelo que vi, não poderia simplesmente trocar onde utilizo o dbSeek(), tem a questão de informar apenas uma unica letra, por exemplo.
Chris, primeira coisa: o dbSEEK e o SEEK funcionam da mesma forma e agem a partir do PRIMEIRO caractere do campo. Veja exemplo do "JOSE JOAQUIM", acima... Já o OrdWildSeek caça qualquer caractere dentro de um campo inteiro, não importa se no começo, meio ou fim.

Segunda: sobre procurar apenas uma letra, o SEEK e DBSEEK também procuram, mas qual a qualidade do resultado? Exemplo: vá no Google e mande procurar por "A". Vai achar um monte de coisa, mas (quase certeza) nada do que você está procurando, não é? Então você precisa "melhorar" o seu pedido, fechar o foco. Tente aumentar de "A" para "AVA"... Mudou bastante, não é?

Tradução: "ajude o Google (ou a OrdWildSeek) a ajudar você a achar o que vc precisa."
EM TEMPO:
Pensa no OrdWildSeek como um "LOCATE" melhorado.
Ele tem SEEK no nome, mas é outro nível.
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Agrupamento na mesma tabela usando indices

Mensagem por alxsts »

Olá!

O conteúdo deste post, sobre o assunto é fantástico!

Managing Hierarchical Data In MySQL
[]´s
Alexandre Santos (AlxSts)
Responder