Página 2 de 3

Re: Filtro com OrdScope()

Enviado: 23 Mai 2008 21:24
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)

Re: Filtro com OrdScope()

Enviado: 24 Mai 2008 08:08
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.

Re: Filtro com OrdScope()

Enviado: 25 Mai 2008 19:37
por Luciano Bonfim
já tentou inverter o índice: tipo+dtos(data)

.

Enviado: 26 Mai 2008 09:01
por Grings
.

Re: Filtro com OrdScope()

Enviado: 26 Mai 2008 09:43
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

Enviado: 26 Mai 2008 10:07
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.

Re: Filtro com OrdScope()

Enviado: 26 Mai 2008 14:55
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.

Enviado: 26 Mai 2008 18:30
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?

Re: Filtro com OrdScope()

Enviado: 27 Mai 2008 10:00
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)

Enviado: 27 Mai 2008 10:42
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.

Enviado: 27 Mai 2008 10:58
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. :)

Re: Filtro com OrdScope()

Enviado: 27 Mai 2008 11:45
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...)

Re: Filtro com OrdScope()

Enviado: 28 Mai 2008 09:50
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)

Re: Filtro com OrdScope()

Enviado: 28 Mai 2008 10:41
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.

Enviado: 28 Mai 2008 11:42
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.