Página 6 de 7
Uso de letodb
Enviado: 17 Jun 2024 16:51
por leandrolinauer
Boa tarde Itamar.
"
Já disse pra ele o que fazer. Infelizmente ele não entendeu.
"
R: Parece que sim, não entendi, poderia ser mais claro porque nunca utilizei nada parecido.
"
Separar antes, pra não precisar ficar varrendo o DBF todo, mas ele disse que usar RELATION... AI eu não sei pq não uso isso desde muito tempo.
"
R: Coloquei neste módulo de pesquisa de produtos o RELATION mas não adiantou pra nada, DBSEEK estava fazendo a mesma coisa.
Motivo: Tenho uma tabela de produtos para cada loja em pastas diferentes, exemplo: nome do arquivo CEST0300.DBF
C:\DADOS\LOJA0001\BANCO\CEST0300.DBF ->LOJA 1 MATRIZ
C:\DADOS\LOJA0002\BANCO\CEST0300.DBF ->LOJA 2 FILIAL
C:\DADOS\LOJA0010\BANCO\CEST0300.DBF ->LOJA 10 FILIAL
O módulo é pra edição do cadastro dos produtos, então devo abrir todos eles em todas as pastas, certo, abro eles.
como não sei qual a pasta peço para o sistema rodar o CEMP0000 (cadastro das lojas) abrindo os arquivos e depois pesquisando os registros no caso com WHILE
Motivo: A pesquisa tanto pega um item, como 10 ou todos para mostrar na tela para editar de acordo com o usuário com o selecionamento.
Mas para pegar o mesmo registro em cada loja, ou faço um SEEK ou RELACIONO os registros.
SEEK leva o mesmo tempo do RELATION, então não adiantou eu relacionar as tabelas das filiais com a da MATRIZ.
Se eu faço uma pesquisa com um item ou outro com tomada pelos indices GRUPO, SUBGRUPO etc, aí sai rapidão, porque é claro, uso o índice, mas pra tabela toda, mesmo fazendo pelo grupo leva o tempão, pq vai pegar todos os dados.
Então dei uma olhada no SCOPE e vi que ele me resolveria mostrando o DBF da tabela ao invés do temporário, o que torna instantâneo.
Claro, se ainda não entendi é pq estou conhecendo estas opções agora, quanto a índices TEMPORARY ou MEMORY não entendi mesmo qual a diferença.
"
Tá relacionando 8 mil itens x 10 filiais. 80 mil itens... Não sei não vi o código.
Eu faço isso só que com INDEX FOR TEMPORARY e é quase instantâneo para 12 meses, em media 10 mil registros por mês.
"
R: Poderia me passar um exemplo um pouco mais detalhado?
Boa tarde José Quintas.
"
Se processa tudo, pesquisa tudo..... o relacionamento serve pra que ?
Sei lá....
"
R: Serve exatamente para pegar os registros em arquivos diferentes, devido a preço, estoque.
Fico muito grato a todos que puderem me elucidar melhor, a única coisa que sei é que precisava de relatórios e pesquisas tipo instantâneas, como fazê-las não tenho a idéia lucida sobre isto.
Vou pesquisar mais sobre indices temporarios.
Um abraço.
Uso de letodb
Enviado: 17 Jun 2024 20:02
por Itamar M. Lins Jr.
Olá!
É simples.
Como eu crio um indice com a clausula FOR ?
PoR exemplo ficha KARDEX da saida do produto com a palavra "CIMENTO" nome no meio de milhares de produtos.
INDEX ON produto TAG temp01 FOR "CIMENTO" $ produto TEMPORARY //Não tenho necessidade de criar milhares de indices 1 para cada produto por isso faço temporary pq irá ser jogado fora.
Depois disso faço um DO WHILE nesse indice só com esse produto. Pode ser EXATO só usar o código ou EAN etc.
DO WHILE .NOT. EOF()
Quando fechar o DBF, esse indice é descartado. Quer dizer dentro da ORDBAG(CDX) deixará de existir.
É só isso ai, mais nada.
No LetoDB:
Código: Selecionar todos
...
If re->(ordNumber("RE100")) > 0
re->(ordDestroy("re100"))
EndIf
...
cQuery := " dtos(vencimento) >= '"+DToS(dIni)+"' .and. dtos(vencimento) <= '"+DToS(dFim)+"' .and. empty(pagamento) "
OrdBy := "cliente + dtos(vencimento) + cod_venda"
...
Index on &OrdBy Tag re100 for &cQuery temporary additive
...
Revelar as variáveis antes, pq o servidor LetoDB não sabe, não enxerga elas. Mesma coisa do SQL.
Basicamente é isso ai em cima. Faça com o produto que vc quer na matriz, abre as filiais e faz a mesma coisa.
LetoDb não sabe o que é dINI(data incial), dFim(Data final), não sabe de nenhuma variável.
Saudações,
Itamar M. Lins Jr.
Uso de letodb
Enviado: 17 Jun 2024 20:29
por Itamar M. Lins Jr.
Olá!
Usando OrdScope()
No lugar de SET RELATION. (pra cortar/separar o que vc quer) dos demais registros.
Desejo separar todos os REGISTROS no arquivo de PRODUTOS VENDIDOS do mês de JANEIRO. cerca de 10 mil itens.
Primeira coisa é existir o INDICE com o CÓDIGO (Numero do Pedido) ou numero da NFe, ou outra coisa que vc use para saber de quem é.
Vamos supor que o REGISTRO(PONTEIRO) está em algum lugar do DBF PRINCIPAL ou USANDO um código(variável)
Estando o arquivo INDEXADO só basta isso ai em baixo. O arquivo que vai "receber" a ORDSCOPE()
(cArq)->(OrdScope(0, cab->pedido) ) //CAB é o ALIAS da MATRIZ ou do PEDIDO etc...
(cArq)->(OrdScope(1, cab->pedido) )
ou -> cCodigo := cab->pedido ou cab->nfe ou cab->ean
(cArq)->(OrdScope(0,cCodigo) )
(cArq)->(OrdScope(1,cCodigo) )
É só isso mesmo!
(cArq)->(OrdScope(0,cab->pedido) ) //O ZERO é o INICIO da CONDIÇÃO
(cArq)->(OrdScope(1,cab->pedido) ) //1 UM é o FIM da CONDIÇÃO
Aqui ele CORTOU o DBF retirou lá dos 10 mil apenas os itens do PEDIDO em questão.
EOF() e BOF() funciona!!!!
(cArq) -> (DbGoTop())
DO WHILE (cArq) -> ( ! eof() )
(cArq) -> (Dbskip())
ENDDO
Para DESLIGAR o ORDSCOPE!
(cArq)->(OrdScope(0,) )
(cArq)->(OrdScope(1,) )
Ou fechar o DBF que a ESCOPO(ORDEM) desliga.
TREINE ai com coisa SIMPLES! por favor! depois vc vai complicando!
Saudações,
Itamar M. Lins Jr.
Uso de letodb
Enviado: 17 Jun 2024 20:35
por ivanil
Mate uma curiosidade minha:
qual o conteúdo dessa função?
ShowWaitProc()
Uso de letodb
Enviado: 17 Jun 2024 20:44
por ivanil
é que essa função é chamada linha a linha do while... isso deve pesar legal, porque teoricamete há trafego alem de atualizar a tela 1 a 1... talvez uma chamada a cada 500...
Uso de letodb
Enviado: 17 Jun 2024 20:49
por Itamar M. Lins Jr.
Olá!
Apaguei, fiquei na duvida, deixa ele responder...
Mesmo assim não precisa.
Acho que faltou o ShowWaitProc(.T.) -> .T. //mesmo assim deve degradar, ligar, pois fica chamando.
Saudações,
Itamar M. Lins Jr.
Uso de letodb
Enviado: 17 Jun 2024 21:09
por JoséQuintas
Você não está sendo muito claro nisso tudo.
Se entendi direito, está processando o equivalente a milhões de registros, ao invés de apenas 80.000
Só dá pra tentar adivinhar.....
Se no arquivo de fora filtra departamento, seção, códigos, etc.... é de se supor que está trabalhando com o arquivo de produtos da matriz.
Se no arquivo de dentro é cada filial, está processando 8.000 produtos pra cada produto da matriz.
8.000 x 8.000, 64 milhões.
pra 10 filiais, 640 milhões.
Sei lá.... tá confuso isso....
E esse IIF() maluco, confunde mais ainda.
Uso de letodb
Enviado: 17 Jun 2024 21:32
por ivanil
Ele tem um cadastro de locais;
Ele faz um scan nesta tabela para varrer a estrutura e abrir os arquivos por locais distribuídos nos diretórios;
Nesses arquivos locais é que feito a varredura do que ele precisa com aquele monte de condições para criar a tabela temporária;
se só tem 8000 registros por tabela, a única coisa que me vem a mente é essas chamadas do ShowWaitProc...
Se fosse eu que estivesse com este problema, começaria por duplicando à rotina, desligaria todas as relações; tiraria os acompanhamentos e faria uma leitura bruta, porem limpa, 100% para medir o tempo, isso daria umas respostas que ele precisa. Pode ser tanta coisa e, ao mesmo tempo, pode ser uma bobagem qualquer que passa despercebido.
Uso de letodb
Enviado: 17 Jun 2024 21:48
por JoséQuintas
Código: Selecionar todos
STATIC PROCEDURE New_BuscaProduto( oModo )
LOCAL cFilter := ".T."
DO CASE
CASE Left( wMerc, 2 ) != "99" .AND. Substr( wMerc, 3, 2 ) != "99".And. Right( wMerc, 3 ) =="999"
cFilter += [ .AND. Left( CODIGO, 4 ) == "] + LEFT( wMerc, 4 ) + ["]
CASE Left( wMerc, 2 ) # 99 .AND. Right( wMerc, 5 ) === "99999"
cFilter += [ .AND. Left( CODIGO, 2 ) == "] + LEFT( wMerc, 2 ) + ["]
CASE wMerc != "99999999"
cFilter += [ .AND. CODIGO == "] + CODIGO + ["]
ENDCASE
IF oGrupo != "9999"
cFilter += [ .AND. GRUPO == "] + oGrupo + ["]
ENDIF
IF oSubGrupo != "9999"
cFilter += [ .AND. SUBGRUPO == "] + oSubGrupo + ["]
ENDIF
IF oMarca != "9999"
cFilter += [ .AND. MARCA == "] + oMarca + ["]
ENDIF
IF oModelo != "9999"
cFilter += [ .AND. MODELO == "] + oModelo + ["]
ENDIF
IF oLinha != "9999"
cFilter += [ .AND. LINHA == "] + oLinha + ["]
ENDIF
IF oClasse != "9999"
cFilter += [ .AND. CLASSE == "] + oClasse + ["]
ENDIF
ShowWait(,,"Selecionando registros...")
DbSelectArea("CEST0300") //seleciono o principal aberto da loja
SET FILTER TO &(cFilter)
GOTO TOP
DO WHILE CEST300->( ! Eof() ) .AND. ! wSaida
wSaida := ExitSeek()
ShowWaitProc()
CEMP0000->(dbGoTop())
DO WHILE CEMP0000->(!Eof())
wSaida:=ExitSeek()
ShowWaitProc()
IF o_Acao == 6 .AND. CEMP0000->C_LOJA==wFilial
lMatriz := .T.
ELSEIF wGEco == "99999999" .OR. Left( CEMP0000->E_CGC, 8 ) == wGEco
lMatriz := ( wLoja == "0001" .OR. wLoja == CEMP0000->C_LOJA )
ELSE
lMatriz := .F.
ENDIF
IF ! lMatriz
SKIP
LOOP
ENDIF
hE_CGC := Left( CEMP0000->E_CGC, 8 )
fP := CEMP0000->C_LOJA
v_Merc := CEST0300->CODIGO
a_Area := "C300" + fP
w_vTXT := fP + " - " + v_Merc + " - " + CEST0300->DESCRICAO
DO CASE
CASE o_Busca ; lFilial := .T.
CASE o_Acao == 1 ; lFilial := .T.
CASE o_Acao == 2 ; lFilial := ( a_Area->P_VALOR > 0 )
CASE o_Acao == 3 ; lFilial := ( a_Area->DESCONTO > 0 )
CASE b_Acao == 1 ; lFilial := ( a_Area->Basico == "B" )
CASE b_Acao == 2 ; lFilial := ( a_Area->Basico != "B" )
CASE b_Acao == 3 ; lFilial := .T.
CASE c_Acao == 1 ; lFilial := ( a_Area->E_AT $ " S" )
CASE c_Acao == 2 ; lFilial := ( a_Area->E_AT == "N" )
CASE c_Acao == 4 ; lFilial := ChkInc()
OTHERWISE lFilial := .T.
ENDCASE
DO CASE
CASE o_Acao == 6 .AND. v_Acao == 1; lFilial := ( a_Area->ATUAL > 0 )
OTHERWISE ; lFilial := .T.
ENDCASE
IF lFilial
(File1Tmp)->( DbAppend() )
(File1Tmp)->LOJA := fP
(File1Tmp)->UF := CEMP0000->E_UF
(File1Tmp)->E_CGC := hE_CGC
(File1Tmp)->CODIGO := (a_Area)->CODIGO
(File1Tmp)->TICADO :=" "
(File1Tmp)->E_AT := (a_Area)->E_AT
......demais campos necessarios
ENDIF
CEMP0000->(dbSkip(1))
ENDDO
CEST300->( dbSkip(1) )
ENDDO
CloseWindow()
RETURN Nil
Sei lá....
Tem também um ChkInc() aí no meio.
Tem mais arquivos envolvidos.
Difícl entender tanto filtro no primeiro, aparentemente com código de produto, e depois o outro aparentemente sem filtro relacionado.
Uso de letodb
Enviado: 18 Jun 2024 09:15
por leandrolinauer
Bom dia a todos.
"Itamar : INDEX ON produto TAG temp01 FOR "CIMENTO" $ produto TEMPORARY"
Uma dúvida, este índice seria criado ao acessar o cadastro do produto mas ele não ficaria demorado para criar ele, como na criação dos índices fixos da tabela?
"Ivanil : ShowWaitProc()"
É apenas uma função de processamento para mostrar na tela o andar do processamento, mostra de 100 em 100 registros, de 1 em 1 fica insuportável (rsrs).
Esta função fazer um carrinho de compras e um boneco andando para progressão, senão o usuário acha que travou.
Lá nas seleções só passa em algumas das funções se oAcao for correspondido, senão nem vê.
ChkInc() = checa os itens incompletos, faltando dados, tais como, peso, preço, ncm, cest, etc.
"José Quintas : While 8.000 registros"
Exemplo mais enxuto:
3 tabelas em 3 pastas diferentes de produtos.
1ª tabela é a da MATRIZ, a principal com todas as informações do produto e o estoque da MATRIZ.
as demais tabelas são das filiais no servidor principal, uma copia exata dos dados do produto mas o estoque, preço é dela própria.
Ao pesquisar, devo colocar na tela todos os dados de todas as lojas: exemplo tabela X
LOJA CÓDIGO DESCRICAO PREÇO ESTOQUE
0001 - 00001 - CIMENTO TAL - 10,00 20,00
0002 - 00001 - CIMENTO TAL - 11,50 15,00
......
0010 - 00001 - CIMENTO TAL - 9,50 30,00
Então para eu pegar as informações destas outras tabelas de acordo com o item selecionado na pesquisa, se for um ou todos, faço da seguinte forma:
While no principal da MATRIZ
pego o produto
While no banco das lojas
posiciono no item desejado acima nesta loja, através de um SEEK ou RELATION, da na mesma até em velocidade de processamento.
gravo os dados do produto já selecionado acima pegando os dados do principal e da loja selecionada como preços e estoque.
E assim vai na tabela toda MATRIZ ou somente nos itens desejados na pré-seleção feita antes.
Então, se tenho 8.000 itens e quero mostrar todos, pego os 8.000 itens x cada loja pra mostrar os valores como a tabela X acima.
se forem 10 lojas, daria 80.000 itens no temporário, a gente reclama da velocidade, mas imagina fazer isto no papel, leva anos.
Assim o usuário tem na tela os dados de todas as lojas.
Claro, daria pra fazer de n formas diferentes este acesso dos dados, fiz este modelo a anos atrás pelo menos uns 20 anos.
Até pesquisei na internet alguns modelos, mas tbem descobri outros menos eficazes do que este método meu aplicado.
Quanto ao SCOPE, creio que seria a melhor situação pra mim, eliminando os índices neste modulo.
Fiz teste em uma tabela de cidade e ficou muito show, será uma ótima opção, mas para eu usar na tabela de produtos, tenho que melhorar uns índices nela, farei.
Quanto a remover as seleções para fazer teste do while, leva um tempo tbem para percorrer a tabela toda, digo tabela toda quando uso pegar todos os itens.
Creio que respondi a todos, se houver mais dúvidas é só perguntar.
Vou fazer uns testes com a clausula TEMPORARY pra ver a performance.
Grato a todos, um abraço.
Uso de letodb
Enviado: 18 Jun 2024 10:17
por JoséQuintas
Quer ver matriz e filiais no browse, é isso?
No estilo SQL seria um SELECT, então, fazer igual.
Código: Selecionar todos
aFiliais := { "fil1\arquivo", fil2\arquivo", "fil3\arquivo" }
USE MATRIZ
SET FILTER TO &( cFiltro )
oTBrowse := { ;
{ "MATRIZ", { || matriz->produto } } }
FOR EACH cFilial IN aFiliais
cAlias := "FIL" + StrZero( cFilial:__EnumIndex(), 2 )
USE ( cFilial ) ALIAS ( cAlias )
FOR EACH xAlias IN cAlias
AAdd( oTBrowse, ;
{ xAlias, { || ( xAlias )->( DBSeek( matriz->Produto ) ), ( xAlias )->NomeCampo } } )
NEXT
NEXT
Browse( oTBrowse )
Ainda pode destacar as colunas com preço baixo, pra chamar atenção, ou sei lá o que.
E se gostarem da idéia, coloca monitor gigante pra ter mais colunas ao mesmo tempo.
zebrado no browse vai ser útil.
Uso de letodb
Enviado: 18 Jun 2024 10:58
por Itamar M. Lins Jr.
Olá!
Uma dúvida, este índice seria criado ao acessar o cadastro do produto mas ele não ficaria demorado para criar ele, como na criação dos índices fixos da tabela?
É bem rápido.
Saudações,
Itamar M. Lins Jr.
Uso de letodb
Enviado: 18 Jun 2024 11:14
por Itamar M. Lins Jr.
Olá!
Antigamente, eu não usava assim, trabalhava da forma que vc ainda trabalha. Fazendo DO WHILE no DBF todo.
Agora sempre, PRIMEIRO separo o que quero com INDICE TEMPORARY com a CLAUSULA FOR. Sempre e ORDSCOPE().
Te digo que em muitos casos é difícil perder para SGBD em velocidade. Tem que montar o servidor dedicado com 32Gib core i9, para fazer frente ao LetoDb. Se botar CPU dessas padrão core i5, 8Gib e não dedicado, como é o caso da maioria das lojas, o LetoDb é bem mais rápido, digo isso pq já comparei com Postgres e ele perdeu. Lógico que se colocar em maquinas melhores, é outra performance.
Saudações,
Itamar M. Lins Jr.
Uso de letodb
Enviado: 18 Jun 2024 21:42
por leandrolinauer
Valeu Itamar
Vou fazer testes desta forma, demoro um pouco pq não tenho muito tempo livre pra programar, mas em breve pretendo ter, me dedicar exclusivamente só para meus clientes com sistema.
Grato
Uso de letodb
Enviado: 19 Jun 2024 21:03
por JoséQuintas
Só curiosidade:
Na sua assinatura indica usar SQLite3 e Firebird.
Como faz o uso deles?