1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

  2. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

Duvida FOR EACH "complexo"

Discussão em 'Progress 4GL' iniciado por jc01, Março 9, 2015.

  1. Cobra.cne

    Cobra.cne Equipe de Suporte Moderador

    Richard, fiquei intrigado com a pergunta e fiz um teste agora, abaixo o resultado.

    Observei no caso o max e min que os tempos são basicamente iguais, em alguns momentos mais rápidos em outros mais lentos (isso em milissegundos), porém no caso do count em todas as vezes que rodei pelo SQL sempre demorou um pouco mais ( +- 20 milissegundos).

    Código usado:
    Código:
    DEFINE VARIABLE imax-emitente AS INTEGER     NO-UNDO.
    ETIME(TRUE).
    FOR EACH emitente fields(cod-emitente) NO-LOCK: 
        ACCUMULATE emitente.cod-emitente (MAXIMUM).
    END.
    DISPLAY "MAXIMUM FOR EACH=" (ACCUM MAXIMUM emitente.cod-emitente) SKIP
            "ETIME=" ETIME SKIP
        WITH NO-LABELS.
    
    
    ETIME(TRUE).
    SELECT MAX(cod-emitente) INTO imax-emitente FROM emitente.
    
    DISPLAY "MAXIMUM SELECT =" imax-emitente SKIP
            "ETIME=" ETIME SKIP
        WITH NO-LABELS.
    
    
    DEFINE VARIABLE icount-emitente AS INTEGER     NO-UNDO.
    ETIME(TRUE).
    FOR EACH emitente fields(cod-emitente) NO-LOCK: 
        ACCUMULATE emitente.cod-emitente (COUNT).
    END.
    DISPLAY "COUNT FOR EACH=" (ACCUM COUNT emitente.cod-emitente) SKIP
            "ETIME=" ETIME SKIP
        WITH NO-LABELS.
    
    
    ETIME(TRUE).
    SELECT COUNT(DISTINCT(COD-EMITENTE)) INTO iCOUNT-emitente FROM emitente.
    
    DISPLAY "COUNT SELECT =" iCOUNT-emitente SKIP
            "ETIME=" ETIME SKIP
        WITH NO-LABELS.
    Resultado:
    Código:
    MAXIMUM FOR EACH=          49.917
    ETIME=           59
    MAXIMUM SELECT =         49.917
    ETIME=           61
    COUNT FOR EACH=          7.346
    ETIME=           59
    COUNT SELECT =         7.346
    ETIME=           83
    

    Infelizmente estou sem uma ferramenta para monitorar a tabela do banco de dados para ver isso em termo de registros lidos.

    Sugiro para cada caso e tabela alguns testes, e isso também vai depender dos campos e índices existentes.

    Abs.
  2. bootstrapmaster

    bootstrapmaster Moderator Moderador Equipe de Suporte

    mas ai que tem um detalhe que infelismente possa matar o seu select, pelo que percebi o select vai registro a registro e calcula o MAXIMO por exemplo, mas em termos da tabela emitente, é logico que devemos analisar caso a caso, como o cod-emitente é campo chave, se vc fizer um find last emitente no-lock no-error. o ultimo codigo vem pra vc na hora, pra saber o primeiro, find first emitente no-lock no-error, com certeza não terá comparação com os selects, agora o COUNT, esse não tem jeito, tem que ir registro a registro contando mesmo.
  3. edney

    edney Membro Participativo

    Eu sai do Oracle e entrei no Progress, tambem estava indignado com os poblemas do SQL nele, mas com o tempo digo que FOR EACH é muito mais bacana, pois em SQL, para resultador compostos, vc tem que fazer JOIN´s complexos, INNER JOIN´s, etc, e quando um registro não aparece, ou quando aparece mais de uma vez é um "deus nos acuda" para achar o problema. Com FOR EACH fica mais claro entender o processo. Pode ser um retrocesso, pode ser, mas hj eu me acostumei tanto com FOR EACH e não sinto mais falta do SQL
  4. bootstrapmaster

    bootstrapmaster Moderator Moderador Equipe de Suporte

    Eu vi outro dia uma linha de select que tinha de tudo, até case para agrupamento de totais, uma tripa de comandos quase impossível de se ler (lembrei do POG), quando eu desenvolvi aplicativos para web, usando php e sql, eu fazia o select e depois tinha que fazer um loop lendo o resultado do select, (fetchrow da vida, não lembro mais dos comandos), agora com o for each eu consigo fazer a seleção dos registros e na iteração do loop já tratar os dados, ignorar se precisar (next), apagar registros, eu acredito que seja melhor, vc pode no progress simular o processo do sql usando queries, vc faz uma pre-seleção e depois interagir só nos registros que estão na query, mas eu ainda prefiro ir direto ao assunto com o for each.
    Tanto que ai fica um dilema para quem desenvolve em OOP, eu crio uma classe, onde eu vou ler dados de uma tabela, então, dependendo da metodologia que vc usar, vc tem VOs, então, se vc ler 10 registros, terá 10 VOs para devolver à aplicação, essa aplicação terá que através de um repeat ou um do while correr a lista de VOs, vc pode também criar a sua classe, que já terá os métodos gets de cada campo, dai vc teria o motor de leitura com métodos findFirst, findNext, findPrev, FindLast posicionando o registro e vc pode fazer os gets dos campos.
    Em termos de usabilidade, as classes, tanto de um jeito como de outro são melhores, mas vc fazer um for each e um display dos campos é tão simples e é eficiente que vc acaba ficando na duvida, desenvolvo em OO ou em PROCEDURAL ?
    Isso em termos de classes de base, que acessam o banco, agora para cálculos, processos de consistência e rotinas de validação e outras coisas, OO é bem melhor, criei uma classe que tem todas as funções relacionadas a cálculos de juros PRICE, SAC, juros por parcelas(de 30 em 30 dias), por dias(considerando sabados e domingo), vc vai criando pequenas classes para cada função e junta tudo em uma classe PROXY, devolve até as datas dos vencimentos e tudo mais, ai sim, vc ve muita vantagem no OO, e acaba vendo vantagem em até substituir o velho for each por uma classe.

Compartilhe esta Página