Página 1 de 1

Indices por Relacionamento

Enviado: 14 Jan 2015 10:32
por Clash
Olá amigos,

O Clipper mais uma vez me surpreendendo! Então resolvi compartilhar com vocês.

Em relatórios, costumo usar índices temporários, uma vez que não acontecerá alterações nos dados da tabela, pois é só consulta, serão descartados. (Respeitando a aula me passada pelo amigo Rochinha na importância de índices, mesmo temporários, acompanhar os índices principais uma vez que utilizados em alterações). Bom mas continuando...

Em um relatório do Controle de Caixa, eu precisava separar documentos, por data e por situação/tipo (débito ou crédito) e ainda permitir ao usuário, escolher a ordem da listagem, por documento ou por emitente (alfabética), só que na tabela de CAIXA eu só armazeno o código ( COD_EMIT ).

Daí já fui logo pensando... -"Nossa, terei que criar uma tabela temporária, cópia da tabela CAIXA, porém com um campo EMITENTE para assim armazenar o nome. Mais tabelas temporárias, não!!" Então, pensei eu já relacionava a tabela CAIXA com CLIENTES para no DbEdit eu exibir o nome do EMITENTE, porque não tentar indexar por este relacionamento. Não é que deu certo!! Me preocupei se não ia bagunçar os índices nativos da tabela CLIENTES, mas não, está perfeito.

Vou tentar explicar mais durante o código...

Código: Selecionar todos

*----------------*      && RELATORIO DO CAIXA &&
PROCEDURE SCA0864
Save Screen to Rel0864
Sombra(12,09,18,63,tCorMold6,8)
Set Cursor On
nCodConta  := 0
dData_Ini    := Ctod("")
dData_Fim  := Ctod("")
cSituacao    := " "
cEntre_Dta  := "N"
cResumido   := "N"
cOrdem       := "1"
cExpressao  := ""
cConfirma   := "N"
Do While .t.
   **
   ** Monto a Tela para Solicitar as Opções **
   **
   @ 13,30 Say "(D)ébitos / (C)réditos / (A)mbos"
   @ 14,30 Say "(S)im / (N)ão"
   @ 15,30 Say "(S)im / (N)ão"
   @ 16,30 Say "(1) Emitente / (2) Documento"
   @ 17,30 Say "(S)im / (N)ão"
   **
   ** Agora os GET´s **
   **
   @ 13,10 Say "Tipo Documento:" Get cSituacao  Pict "!" Valid PROC_TIPO(cSituacao)
   @ 14,10 Say "Entre Datas...:" Get cEntre_Dta Pict "!" Valid PROC_CTDTA(cEntre_Dta)
   @ 15,10 Say "Totalizado....:" Get cResumido  Pict "!" Valid cResumido$"SN"
   @ 16,10 Say "Ordenado por..:" Get cOrdem     Pict "!" Valid cOrdem$"12"
   @ 17,10 Say "Confirma......:" Get cConfirma  Pict "!" Valid cConfirma$"SN"
   Read
   If Lastkey() == 27  &&--> Para sair do Loop de Confirmação das Opções pelo Usuário e sair da Rotina
      DBCLOSEALL()
      Exit
   EndIf
   If cConfirma == "N"
      Loop
   EndIf
   Exit
EndDo  &&--> Loop caso o Usuário não Confirme as Opções
*
If Lastkey() == 27 
   Rest Screen From Rel0864
   Return
Endif
*
* Aqui monto uma expressão para usar como condicional na criação do índice temporário
*
If cSituacao <> "A"
   cExpressao := "CAIXA->TIPO == '" + cSituacao + "'" + " "
EndIf
If cEntre_Dta <> "N"
   cExpressao := "CAIXA->DATA >= dData_Ini .and. CAIXA->DATA <= dData_Fim"
EndIf
*
Select 0
ABREARQ("CLIENTES", .t., "CLIENTES")
ORDSETFOCUS("CODIGO")
*
Select 0
ABREARQ("CAIXA", .t., "CAIXA")
Set Relation to COD_EMIT into CLIENTES   &&-->Relaciomento da Tabela CAIXA com CLIENTES.
*
If cOrdem == "1"  &&-->Ordem por Emitente (Alfabética)
   *
   Index on CLIENTES->NOME to &tLocal\TPCAIXA for &cExpressao    &&--> E aqui usei o Índice relacionado
   *
 ElseIf cOrdem == "2" &&-->Ordem por Documento (Numérica)
   *
   Index on NOTA to &tLocal\TPCAIXA for &cExpressao
   *
EndIf
Go Top
*
** Daqui para baixo monto o relatório.
*
Tentei deixar da forma mais clara possível, mas qualquer dúvida, estou a disposição.

Abraço aos amigos do fórum e VIVA o CLIPPER!!!

Indices por Relacionamento

Enviado: 14 Jan 2015 11:52
por Pablo César
Isso ai ! :)

Indices por Relacionamento

Enviado: 14 Jan 2015 11:56
por billy1943
O nosso amigo usou aquilo que sempre aparece na "área cinzenta" do Clipper, ou seja, o comando SET RELATION e uma utilização para o DBEDIT, o qual uso a larga em meus sistemas, ao contrário do TBROWSE.

Apenas acresceria que o comando SET RELATION funciona como um SEEK aplicado ao arquivo filho mas considerando SOFTSEEK como OFF, pois usamos sempre colocá-lo em ON, tentar o acesso e voltá-lo para OFF em seguida.

Muita válida a sugestão, visto que as expressões que poderão fazer parte do índice provisório podem ser inúmeras, facilitando enormemente a procura dos registros, e pode ser usado em arquivos de qualquer tamanho, por não ter
limitações de filtro ou outras ações que "seguram" o processamento.

Indices por Relacionamento

Enviado: 15 Jan 2015 09:52
por Clash
Obrigado Billy1943.

Eu já pensei muito em passar para o TBROWSE, mas eu só uso DbEdit, nos cadastros, em resultados de consulta, sempre me atendeu bem.

Abraço.

Indices por Relacionamento

Enviado: 17 Jan 2015 16:08
por Eros
Bom, para esses casos, eu uso matrizes.. coloco o indice que o usuario desejar, sem precisar criar arquivos, sem criar indices temporarios, e com 1/4 do tempo de indexaçao.

Matriz é uma maravilha da matematica.

Indices por Relacionamento

Enviado: 17 Jan 2015 21:15
por JoséQuintas
Na prática as opções se multiplicam.
Poderia também indexar por uma função, e a função retornar o que quiser.

A gente acha isso bom, até conhecer base SQL.

Indices por Relacionamento

Enviado: 22 Jan 2015 08:39
por Clash
Eros,

E como vc obteria o índice por ordem alfabética do nome do Cliente ele não estando na tabela CAIXA?

Valeu.

Indices por Relacionamento

Enviado: 22 Jan 2015 09:33
por Eros
Na hora de adicionar elementos na matriz, você adiciona quais informações vc quer, inclusive, podendo buscar de mais de uma tabela. Depois dos elementos que você adicionou na matriz, vc ordena do jeito que escolher.

Para adicionar elementos (dados) numa tabela, pode ser assim:

Frw := { }

Reagro->( AAdd( Frw , CODIGO() +;
" " +;
ShowCont(8,COD_PRO) +; // Minha função para buscar o nome do cliente em outra tabela
" " +;
Str( QUANT ) +;
" " +;
TIPO +;
" " +;
NOTA +;
" " +;
USER +;
" " +;
Dtoc( DT_REC ) +;
" " +;
Dtoc( DT_NOTA ) ) )


Depois para ordenar os dados na matriz, pode ser usado assim:

aSort( Matriz ,,, { |x,y| x <= y } ) // Por codigo
Asort( MtzRel ,,, { |x,y| Ctod(x[2]) <= Ctod(y[2]) } ) // Por Data

Ou na ordem que voce desejar... tratando por elementos da matriz.

Isso acima, é só um exemplo da codificação. Mas não criei arquivo temporário nenhum e não criei arquivo de índice nenhum. Esta tudo na matriz, ordenado e acessado extremamente rápido.

Indices por Relacionamento

Enviado: 22 Jan 2015 13:04
por alxsts
Olá!

Em Clipper, esta técnica esbarra na limitação da linguagem, de 4096 elementos por dimensão de cada matriz.

Já em Harbour, alem de não existir esta limitação, existe a possibilidade de se utilizar-se hash em lugar de array. Creio que ficaria mais rápido ainda...

Indices por Relacionamento

Enviado: 22 Jan 2015 14:59
por Eros
Sim.. vc tem limitação de 4096 linhas.. porem, voce pode trabalhar com mais de uma matriz... ai, depende do jeito que vc quer desenvolver ne... Essa limitação pra mim, nunca foi problema... mas... programação é igual nescau... tem 1001 maneiras diferentes de se fazer...

Indices por Relacionamento

Enviado: 26 Jan 2015 09:27
por Clash
Boa Eros, valeu pela explicação. Bom conhecer mais um caminho. Em relatórios/consultas que trazem informações não muita extensas, pode ser uma boa.