Filtro com OrdScope()

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

Moderador: Moderadores

Hasse
Usuário Nível 4
Usuário Nível 4
Mensagens: 820
Registrado em: 19 Out 2004 10:30
Localização: Jaraguá do Sul - SC

Re: Filtro com OrdScope()

Mensagem por Hasse »

Olá.

Na minha visão das coisas o texto da documentação da Função OrdScope() está funcionando corretamente, pois vejamos:

The OrdScope() function defines or clears the top and bottom scope for indexed database navigation. The top and bottom scope values define the range of values valid for navigating the record pointer within the controlling index.

Ou seja, ela estabelece o Primeiro Registro e/ou o Último Registro. Nada faz com os registros intermediários.

Vejam. Basta incluir uma única linha, e o resultado está perfeito muita rápido.

Código: Selecionar todos

Function Main()

Request DBFCDX
RddSetDefault('DBFCDX')

Set Date Brit
Set Century On

Scroll()

If !File('Titulos.DBF')
   aStructure:={}
   AADD(aStructure,{'Data_Vecto', 'D' ,0, 0})
   AADD(aStructure,{'Tipo'          , 'C' ,1, 0})

   DbCreate('Titulos',aStructure)

   Use Titulos.DBF New
   For i=1 To 30
       DbAppend()
       Replace Data_Vecto With Date()+i
       Replace Tipo With If(IsImpar(i),'1','2')
   Next
   Index On Dtos(Data_Vecto) + Tipo TAG 1 To Titulos 
   Set Index To Titulos
Else
   Use Titulos.DBF New Index Titulos
EndIf

OrdSetFocus(1)

dDataIni:=Ctod('01/06/2008') 
dDataFin:=Ctod('30/06/2008')

OrdScope(0,Dtos(dDataIni) + '2')
OrdScope(1,Dtos(dDataFin) + '2')

Set Filter to Tipo = "2" //<<<<<<<<<<<<<<<< esta linha.

DbGoTop()

Browse()

Return(.T.)


Function IsImpar(nNumero)
Return((nNumero%2)!=0)
Hasse
CP200 / CP500 / Basic / dBase III / dBase IV / Clipper Summer / RTlink / Exospace.
Clipper 5.3b / Blinker 7.0 / CDX com TAG
xHarbour 1.2.1-6604 / Borland C++ (5.5.1) 32 bit / HBmake.
Harbour 3.2.0dev (r1412121623) / MINGW / HBM2 / MiniGui HMG 3.1.4 / IDE (Roberto Lopez).
"Conheça todas as teorias, domine todas as técnicas, mas, quando tocares uma alma humana, seja apenas outra alma humana." (C.G.Jung)
Hasse
Usuário Nível 4
Usuário Nível 4
Mensagens: 820
Registrado em: 19 Out 2004 10:30
Localização: Jaraguá do Sul - SC

Re: Filtro com OrdScope()

Mensagem por Hasse »

Um lindo e bom dia amigos !!!!

MATEI A CHARADA !!!!!

Duarante a madrugada acordei com a solução na cabeça, não sei como E nem porquê !!! E é simples.

Basta inverter a chave de indexação e de pesquisa. Assim:

Código: Selecionar todos

Index On Tipo + Dtos(Data_Vecto) TAG 1 To Titulos 
...
...
OrdScope(0,"2" + Dtos(dDataIni))
OrdScope(1,"2" + Dtos(dDataFin))
Bom trabalho.
Hasse
CP200 / CP500 / Basic / dBase III / dBase IV / Clipper Summer / RTlink / Exospace.
Clipper 5.3b / Blinker 7.0 / CDX com TAG
xHarbour 1.2.1-6604 / Borland C++ (5.5.1) 32 bit / HBmake.
Harbour 3.2.0dev (r1412121623) / MINGW / HBM2 / MiniGui HMG 3.1.4 / IDE (Roberto Lopez).
"Conheça todas as teorias, domine todas as técnicas, mas, quando tocares uma alma humana, seja apenas outra alma humana." (C.G.Jung)
Avatar do usuário
Luciano Bonfim
Usuário Nível 3
Usuário Nível 3
Mensagens: 414
Registrado em: 23 Ago 2007 09:34
Localização: Rio de Janeiro / São Paulo
Contato:

Re: Filtro com OrdScope()

Mensagem por Luciano Bonfim »

já tentou inverter o índice: tipo+dtos(data)
Muito Obrigado,

Luciano Bonfim de Azevedo
www.bonfim.com.br
luciano@bonfim.com.br
www.linkedin.com/in/lucianobonfim
Skype : lucianobonfim
Grings
Usuário Nível 3
Usuário Nível 3
Mensagens: 340
Registrado em: 18 Ago 2004 13:51

.

Mensagem por Grings »

.
Editado pela última vez por Grings em 22 Mai 2009 20:58, em um total de 1 vez.
MARCELOG
Usuário Nível 4
Usuário Nível 4
Mensagens: 546
Registrado em: 15 Mar 2005 16:54
Localização: Divinópolis/MG

Re: Filtro com OrdScope()

Mensagem por MARCELOG »

Como funcionam os índices e por que eles são rápidos?
Bem, não sei onde li, mas vou tentar explicar.
Quando você usa "set filter" toda a tabela é percorrida para selecionar os registros que atendem a condição. Então, se ela tiver um milhão de registros, todos serão lidos e comparados.
Contudo, se você criar um índice, um arquivo a parte será criado contendo a ordenação pretendida e a referência para o registro no arquivo original.
Logo, considerando datas, o arquivo de índice pode conter algo como 20080525-60, 20080526-32, 20080527-33, .
Conforme se vê, muito embora 20080525 seja o primeiro, ele se refere ao registo 60 no arquivo original.
Mas por que o índice é rápido?
Veja bem, ao ser gravado, considerando que a ordem é fielmente observada, o primeiro registro do arquivo de índice contém o valor médio dos índices.
No nosso exemplo, com apenas 3 registros, o valor do primeiro registro será 20080526-32.
Então se você pesquisar algo pelo índice, o primeiro registro é comparado e, de cara, podem ser eliminados 50% dos registros.
Uma pequisa da data 20080626 por exemplo, faz com que no arquivo de índices, todos os registros antes da metade do arquivo (de índices) sejam desconsiderados.
Dessa forma, trabalhando com índices, o processo natural de seleção e pesquisa fica mais fácil.
Não tem sentido usar ordscope com "set filter".

MarceloG
Água mole em pedra dura tanto bate que até espirra!
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

O que você descreveu, Marcelo, é formalmente conhecido como pesquisa binária, que só é aplicável, como você sabe, em conjuntos de dados já ordenados.
Pra quem tiver interesse na matéria, basta uma pesquisa no Google. Há muito material a respeito desse algoritmo e de várias outras técnicas de ordenação e busca.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Hasse
Usuário Nível 4
Usuário Nível 4
Mensagens: 820
Registrado em: 19 Out 2004 10:30
Localização: Jaraguá do Sul - SC

Re: Filtro com OrdScope()

Mensagem por Hasse »

Boa tarde colegas.

Preciso concordar com o colega MarceloG, em Gênero, Grau e Número com a afirmação dele, que não tem sentido usar filtro combinado com ordscope().

Contudo, se necessário, em arquivos muito grandes, se houver absoluta necessidade de filtro, e houver a possibilidade de, previamente usar ordscope(), a filtragem se torna muito, mas muito mais rápida, visto que a base de dados a ser filtrada é muito menor.
Hasse
CP200 / CP500 / Basic / dBase III / dBase IV / Clipper Summer / RTlink / Exospace.
Clipper 5.3b / Blinker 7.0 / CDX com TAG
xHarbour 1.2.1-6604 / Borland C++ (5.5.1) 32 bit / HBmake.
Harbour 3.2.0dev (r1412121623) / MINGW / HBM2 / MiniGui HMG 3.1.4 / IDE (Roberto Lopez).
"Conheça todas as teorias, domine todas as técnicas, mas, quando tocares uma alma humana, seja apenas outra alma humana." (C.G.Jung)
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

Hasse escreveu:não tem sentido usar filtro combinado com ordscope().
O que não tem sentido é usar algo que não funcione bem. Eu uso SET FILTER e SCOPE juntos em várias situações, e tem funcionado muitíssimo bem, em várias situações. Só a facilidade de programação já justifica o uso. E se o resultado é o mesmo do índice dedicado, como é de fato, pra quê usar um índice dedicado?
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
gvc
Colaborador
Colaborador
Mensagens: 1270
Registrado em: 23 Ago 2005 10:57

Re: Filtro com OrdScope()

Mensagem por gvc »

[MARCELOG]
Vamos por partes.
O SET FILTER ativa o filtro de leitura de registro.
Qdo o clipper move o ponteiro de registro e lê o mesmo do disco, ele verifica se a condição de filtro é valida. Se for, retorna o registro. Se não for, move o ponteiro para o próximo e executa o mesmo procedimento até encontrar um registro válido. Por isso ele se torna lento. O clipper procura o que pode retornar.

[Maligno]
O que o MARCELOG esta falando/postando é a arvore binária. O clipper usa o BTree+ para criar o NTX.
Para entender, imagine que cada página do indice é um array com 5 elementos e cada um contem o campo nome do seu arquivo original.
Se eu tiver até 5 nomes, só terei que ordenar os mesmos e gravar no arquivo NTX. Quando eu for pesquisar, pego o último elemento da página e vou subindo até encontrar um que atenda minha chave de pesquisa.
Essa ordenação na página é o primeiro balanceamento da arvore.
Quando eu colocar um sexto registro, não cabe mais na página. Tenho que quebrar a página inicial em mais 5 páginas.
Movo os 5 registros da página 1 para a página 2. Coloco o registro 6 na página 3. Na página 1 eu coloco o último registro da página 2 como elemento 1 e o último registro da página 3 como registro 2.
Agora eu tenho que ordernar a página 2 com a página 3. Novamente o balanceamento da árvore e gravo a página 2 e 3. Acerto os elemento da página 1 para apontar para o último elemento da página 2 e 3.
Conforme for acrescentando registros no arquivo, a quantidade de página vai crescendo.
Quando eu altero um registro, o arquivo de indice deve verificar a posição dentro das páginas e incluir o novo elemento e fazer o balanceamento.
Pq é usado o último elemento e não o primeiro da página? Pq vc compara com o elemento de cima e vê que ele é menor, vc consegue determinar mais rapidamente a página necessária, dentro dela o mesmo principio até encontrar um registro que atenda sua chave ou que não tenha mais página "abaixo" na árvore.
Se vc tiver registros multiplos, vc terá que procurar na página final sempre o elemento menor ou o primeiro da página (respeitando o algoritmo). Assim vc terá o primeiro registro atendendo sua chave.

Lembrando que o Clipper 5.3 permite procurar o último registro. Então o ponteiro, dentro da página, move-se para baixo.

Ufa! Ajudei ou atrapalhei tudo.

[Grigs]
O ordscope usa o indice para filtrar o arquivo. Por isso ele é incrivelmente mais rápido que o set filter.
Como vc não especificou corretamente o que estava tentando fazer, imagino algo como um arquivo de contas a pagar cujo campo tipo seja usado para indicar paga ou não paga. Pode ser outra coisa, mas vou usar isso como exemplo.
Campo tipo com valor 1 - Não paga. Vc quer saber contas pagas dentro de um período. Seu índice deve ser tipo + data e o ordscope deve usar o mesmo formato e o dbseek tb.
'1' + dtos(data)
"TRS-80/Sincler/Apple/PC - Clipper Winter 85, tlink 1.0 [pc 10 MHz - 640K] {NEZ 8000 2Kb RAM}"
{POG - Programação Orientada a Gambiarra}
Grings
Usuário Nível 3
Usuário Nível 3
Mensagens: 340
Registrado em: 18 Ago 2004 13:51

Mensagem por Grings »

GVC,

Esclarecendo o que pretendo fazer é o seguinte:

Um DBF que contenha os títulos a receber (tipo 1) e a pagar (tipo 2) que serão exibidos em um Tbrowse. Então preciso inicialmente filtrar os registros para que quando faça a manutenção de contas a receber apareçam somente os registros do tipo 1 e quando for a pagar os registros tipo 2 dentro de um determinado período. Estabelecerei um filtro para que mostrar somente os títulos em aberto. Terei, ainda, que criar um índice para localizar o título pelo número, etc. Isso está recém em fase de testes, nada definido.

Abraços,

Grings
Nota de Moderação:
por [url=https://pctoledo.org/forum/memberlist.php?mode=viewprofile&u=100899][color=#00AA00]Pablo César[/color][/url]: Mensagem recuperada através de citações de outros usuários. Pois esta mensagem foi re-editada pelo próprio autor apagando o seu conteúdo e prejudicando o entendimento do tópico. Esta prática não é aceita no fórum.
Editado pela última vez por Grings em 22 Mai 2009 20:54, em um total de 1 vez.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

gvc escreveu:O que o MARCELOG esta falando/postando é a arvore binária. O clipper usa o BTree+ para criar o NTX.
A pesquisa binária é diferente de árvore binária balanceada (ou árvore de pesquisa binária). Já conheço os dois. Mas o que o Marcelo descreveu me pareceu ser a pesquisa binária, que é aliás, o algoritmo que usei no meu sistema de help.

Pra quem não conhece, um exemplo: você lê o ítem do meio e o compara com o valor pesquisado. Se diferente e menor, a metade superior é descartada (elimina 50%). Repete-se o processo até encontrar o ítem ou passar pelo último ítem sem sucesso na comparação. A cada comparação, divide-se a seção em duas partes. Daí vem o nome "binário".

É um assunto interessante. Pra quem quiser se aprofundar, recomendo um livro bem conceituado: "Estruturas de dados usando C", do Tenenbaum. Apesar dos exemplos serem em C, é bem fácil de entender. :)
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
gvc
Colaborador
Colaborador
Mensagens: 1270
Registrado em: 23 Ago 2005 10:57

Re: Filtro com OrdScope()

Mensagem por gvc »

[Grings]
Vc pode usar o FOR para filtrar o arquivo de indice

Código: Selecionar todos

Index On Dtos(Data_Vecto) TAG 1 for tipo = '1' To Titulos 
Index On Dtos(Data_Vecto) TAG 2 for tipo = '2' To Titulos 
Ou se vc tem o campo data de pagamento.

Código: Selecionar todos

Index On Dtos(Data_Vecto) TAG 1 for empty(data_padto) To Titulos 
Index On Dtos(Data_Vecto) TAG 2 for empty(data_padto) To Titulos 
Para ver os titulos abertos, dbsetorder(1).
Para ver os titulos fechados, dbsetorder(2).

Para indexar por titulo

Código: Selecionar todos

Index On Dtos(Data_Vecto) TAG 1 for empty(data_padto) To Titulos 
Index On Dtos(Data_Vecto) TAG 2 for empty(data_padto) To Titulos 
Index On titulo + Dtos(Data_Vecto) TAG 3 To Titulos 
Para procurar por titulo, dbsetorder(3).

[Maligno]
O que o MARCELOG colocou é tb conhecido como SHELL.
Pegue o primeiro, o último e o meio do arquivo.
Verifique se a chave é menor que o inicio ou maior que o final. Se verdadeiro, a pesquisa já terminou.
Verifique o registro do meio do arquivo. Se a chave é menor, esta na 1ª metade. Se a chave é maior, esta na 2ª metade.
Quebre novamente o arquivo na metade dessa determinada anteriormente (agora vc esta com 1/4 do arquivo original).
Continue com o algoritmo até chegar no registro que atenda sua chave ou determinar que não existe registro que o faça.

Só para constar, junto com o turbo pascal (antigo) vinha um programa que mostrava exatamente como isso funciona. Eu recomendo. (Pelé fazendo propaganda do Vitasai - faz tempo...)
"TRS-80/Sincler/Apple/PC - Clipper Winter 85, tlink 1.0 [pc 10 MHz - 640K] {NEZ 8000 2Kb RAM}"
{POG - Programação Orientada a Gambiarra}
Avatar do usuário
Luciano Bonfim
Usuário Nível 3
Usuário Nível 3
Mensagens: 414
Registrado em: 23 Ago 2007 09:34
Localização: Rio de Janeiro / São Paulo
Contato:

Re: Filtro com OrdScope()

Mensagem por Luciano Bonfim »

Grings escreveu:GVC,

Esclarecendo o que pretendo fazer é o seguinte:

Um DBF que contenha os títulos a receber (tipo 1) e a pagar (tipo 2) que serão exibidos em um Tbrowse. Então preciso inicialmente filtrar os registros para que quando faça a manutenção de contas a receber apareçam somente os registros do tipo 1 e quando for a pagar os registros tipo 2 dentro de um determinado período. Estabelecerei um filtro para que mostrar somente os títulos em aberto. Terei, ainda, que criar um índice para localizar o título pelo número, etc. Isso está recém em fase de testes, nada definido.

Abraços,

Grings
Apenas uma dica de modelagem, nesse caso o correto seria ter dois DBFs uma para contas a pagar e outro para contas a receber (mesmo que todos os campos nos dois arquivos sejam exatamente os mesmos)
Muito Obrigado,

Luciano Bonfim de Azevedo
www.bonfim.com.br
luciano@bonfim.com.br
www.linkedin.com/in/lucianobonfim
Skype : lucianobonfim
Avatar do usuário
gvc
Colaborador
Colaborador
Mensagens: 1270
Registrado em: 23 Ago 2005 10:57

Re: Filtro com OrdScope()

Mensagem por gvc »

Luciano Bonfim escreveu: Apenas uma dica de modelagem, nesse caso o correto seria ter dois DBFs uma para contas a pagar e outro para contas a receber (mesmo que todos os campos nos dois arquivos sejam exatamente os mesmos)
Achei melhor não entrar nesse mérito.
Concordo com parte de sua observação.
No campo contas pagas deverá obrigatoriamente aparecer alguns campos como data de pagamento, valor pago, juro, multa.
Eu usei o contas a pagar só para exemplificar. Poderia ser outra coisa. Parece que eu acertei sem querer o que era.
"TRS-80/Sincler/Apple/PC - Clipper Winter 85, tlink 1.0 [pc 10 MHz - 640K] {NEZ 8000 2Kb RAM}"
{POG - Programação Orientada a Gambiarra}
Grings
Usuário Nível 3
Usuário Nível 3
Mensagens: 340
Registrado em: 18 Ago 2004 13:51

Mensagem por Grings »

Se pensar dessa forma, terei que ter um DBF para clientes, outro para fornecedores, um para notas de entradas e outro para saidas, um para ítens de entrada outro para ítens de saída e assim por diante. Isso era o que eu fazia. Estou reescrevendo o programa e na minha opinião é melhor trabalhar com menos arquivos, e é justamente por isso a necessidade dos filtros. O que vcs acham ?
Nota de Moderação:
por [url=https://pctoledo.org/forum/memberlist.php?mode=viewprofile&u=100899][color=#00AA00]Pablo César[/color][/url]: Mensagem recuperada através de citações de outros usuários. Pois esta mensagem foi re-editada pelo próprio autor apagando o seu conteúdo e prejudicando o entendimento do tópico. Esta prática não é aceita no fórum.
Editado pela última vez por Grings em 22 Mai 2009 20:53, em um total de 1 vez.
Responder