Página 1 de 1
Como filtrar muitos registros? Dúvida
Enviado: 09 Fev 2018 18:20
por fladimir
Pessoal deu um branco aki, se alguém puder ajudar, seguinte...
Tenho uma situação q surgiu q tenho uma tabela Mestre q tem o cabecalho com dados como NrInterno e DataLanc, ai tenho uma tabela filha q tem os registros vinculados a esta tabela Mestre.
Dentro desta tabela filha cada registro tem um campo chamado DtViagem
Preciso criar uma consulta q retorne uma filtragem da seguinte maneira, informo o periodo da viagem exemplo 01/01/2018 até 31/01/2018, blz
Ai o q tiver de viagens nessa tabela filha preciso pegar os respectivos registros vinculados da tabela Mestre
Comecei a montar o seguinte código
Pega viagens:
Código: Selecionar todos
Itens->( DBEVAL( { || AADD( aViagens, { Itens->NrInterno, Itens->DataLanc } ) },; // Bloco While
{ || Itens->DtViagem >= dt1 .and. Itens->DtViagem <= dt2 } ; // Bloco For
);
)
Ai a partir desse Array pensei em montar ou um Indice ou um Filter, MAS O X DA QUESTAO ESTA AKI.... pode ficar gigante o negocio...
alguém teria uma ideia sobre o assunto?
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 11:52
por asimoes
Fladimir,
Beleza ?
Informa qual é a estrutura das duas tabelas, mestre e detalhe
A detalhe tem NrInterno e DataLanc e a detalhe ? tem os mesmos campos ? acho que vai ter que ter uma chave nessa consulta talvez o NrInterno
Só uma ideia: corrige ai se eu não entendi direito
Estou supondo que a chave de ligação entre as duas tabelas seja o NrInterno, se for isso eu criaria um indice com NrInterno + DtViagem
Código: Selecionar todos
DO WHILE MESTRE->NrInterno = nNumero .AND. ! MESTRE->( Eof() )
aViagens := {}
DETALHE->( DbSeek( Str( MESTRE->NrInterno ) + DTOS( dt1 ) ) )
DO WHILE DETALHE->NrInterno = nNumero .AND. FILHA->DtViagem <= dt1 .AND. ! FILHA->( Eof() )
AADD( aViagens, { MESTRE->NrInterno, MESTRE->DataLanc } )
DETALHE->( DbSkip() )
ENDDO
MESTRE->( DbSkip() )
ENDDO
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 12:34
por fladimir
A chave é NrInterno + DTOS(DataLanc)
Esses campos tem nas 2 tabelas
Montar o Array eu consegui...
Minha preocupação é se fizer via Indice será q da certo tipo pq o FOR pode ter muitos campos tipo
Vou escrever a grosso modo só pra transmitir a ideia q estou preocupado se não terá problemas.
Tipo:
Código: Selecionar todos
cFiltro := ""
For nI:=1 to Len(aViagens)
If nI >1
cFiltro += ".OR."
endif
cFiltro += [ "(Mestre->NrLanc == "] + aViagens[nI,1] + [" .and. DTOS(Mestre->DataLanc) == "] + DTOS(aViagens[nI,2] + [")]
NEXT
bFiltro := &( ' { || ' + cFiltro + ' }' )
INDEX ...... FOR EVAL(bFILTRO)
Imaginemos q achou 30 viagens Ok... ai como filtrar isso na tabela Mestre, se eu monto um FOR NEXT pra criar um FILTRO e depois passar como INDEX KEY TAG TEMP TO IDX FOR EVAL( bFiltro ) pode ficar muito extenso, será q tem limite isso?
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 13:23
por dbdc5554
ja usei MUITAS condicoes dentro de FOR
acredito NAo ter limite porque é uma Logica ao montar o indice
tipo if ignore else selecione
e pelo que eu VI
MELHOR filtrar do que ignorar registro em um LOOP
Paiva
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 16:02
por fladimir
Blz pessoal, obrigado.
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 16:40
por Eolo
Fladimir, dá uma olhada no ORDSCOPE().
Se a tabela filha está indexada (CDX) por data (dtviagem), é só fazer o seguinte:
odscope(0,ctod("01/01/2018")) // início
odscope(1,ctod("31/12/2018")) // fim
go top
Feito isso, se vc der um browse no DBF, vão aparecer somente os registros que estejam dentro do escopo desejado. Os demais registros continuam lá, mas "invisíveis". GO TOP vai pra 01-jan e GO BOTT vai pra 31-dez.
Tá feito o filtro. Agora é só buscar o resto na tabela pai.
Pra remover o filtro:
odscope(0,nil)
odscope(1,nil)
go top
Mais importante: a filtragem é instantânea.
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 19:13
por asimoes
Pra não ficar um filtro monstro eu pensaria em algo assim
Código: Selecionar todos
cFiltro := [ Mestre->NrLanc >= ] + aViagens[1,1] + [ .AND. Mestre->NrLanc <= ] + aViagens[Len(aViagens),1] + [ .AND. ]
cFiltro += [ DTOS(Mestre->DataLanc) ] >= DTOS(aViagens[1,2]) [ .AND. DTOS(Mestre->DataLanc) <= ] + aViagens[Len(aViagens),2]
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 19:23
por Eolo
Simões, o Ordscope faz isso tudo. Instantâneo.
Eu usei por muito tempo (uma fantástica dica do Sygecom).
O que o Ordscope faz é simplesmente "setar" o TOP e o BOTT como o início e o fim de um escopo, instantaneamente, sem criação de índices adicionais ou pesquisas ou etc. Só os registros que interessam ficam visíveis (filtrados). Instantâneo.
Você já experimentou?
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 20:01
por Eolo
Eu usei isso bastante, num programa de mercado.
Um exemplo: o cadastro de produtos tinha vários índices, um deles por SETOR. O cliente dava um browse nos produtos, escolhia um dos Setores (tipo Laticínios, Carnes, Padaria), o browse na hora mostrava só os produtos do setor escohido. Instantâneo.
Se o objetivo era corrigir em 5% os preços somente daquele Setor, era só fazer GO TOP, DO WHILE !EOF(), REPL PRECO WITH ROUND(PRECO*1.05,2)... Feito. Se era pra imprimir as etiquetas de gôndola do setor, feito.
E esse "filtro" não é um monstro, nada a ver com SET FILTER, por exemplo, ou índices temporários ou o que for. O Ordscope simplesmente fecha o foco (BOF/EOF) sobre o que interessa dentro de um CDX. Instantâneo.
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 20:38
por JoséQuintas
Exato.
Se a tabela vai ficar monstruosa, melhor existir um índice por data, nem que seja necessário criar um arquivo temporário depois pra ordenar.
Pode usar o SET SCOPE, ou até o SEEK Dtos( dDataIni ) SOFTSEEK
Se tiver que processar todos os registros sempre, vai ser demorado, então melhor já ter o índice criado e fazer parte do banco de dados.
Isso vale pra NTX, CDX, MySQL, etc.
Como filtrar muitos registros? Dúvida
Enviado: 10 Fev 2018 20:45
por fladimir
Valeu pessoal pelas ideias, vou bolar algo aki... agradeço.
Q
Enviado: 10 Fev 2018 21:40
por Eolo
Se a tabela vai ficar monstruosa, melhor existir um índice por data, nem que seja necessário criar um arquivo temporário depois pra ordenar.
Pode usar o SET SCOPE, ou até o SEEK Dtos( dDataIni ) SOFTSEEK
Se tiver que processar todos os registros sempre, vai ser demorado, então melhor já ter o índice criado e fazer parte do banco de dados.
Isso vale pra NTX, CDX, MySQL, etc.
Bem lembrado, José!
Fladimir, é fundamental ter índices criados.
Sem um índice, nem OrdScope nem Seek funcionam, talvez nem o Soft Seek. Precisa ter isso em mente.
Sem índice, um browse vai mostrar os dados na ordem em que foram criados.
Totalmente sem sentido, cara.
E criar índices temporários, no run time, com um imenso data base, pode ser improdutivo.
Tem que ficar ligado nisso.
Como filtrar muitos registros? Dúvida
Enviado: 12 Fev 2018 17:20
por rubens
Fladimir,
Com o Ordscope() você ainda pode aplicar um SetFilter depois que ainda vai ficar muito rápido...
Se não satisfazer as condições que precisa... Filtra com Ordscope(), cria uma tabela na memória e joga os dados filtrados nela.. Daí pode criar índices na memória também... ou filtrar com setfilter. Tudo extremamente rápido...
Depois que aprendi usar tabela e índice na memória nunca mais usei vetores/matrizes...
é mais fácil ordenar a tabela do que vetores/matrizes...
Rubens
Como filtrar muitos registros? Dúvida
Enviado: 12 Fev 2018 19:13
por fladimir
Legal Rubens, obrigado pela dica.