Agrupamento e loops

Os comandos GROUP e LOOP oferecem duas formas de execução repetida de uma série de comandos. GROUP executa uma única iteração de um ou mais comandos em cada registro. LOOP executa várias iterações de uma série de comandos em um único registro e somente pode ser usada dentro de um bloco de GROUP.

Um exemplo simples de GROUP

Você tem uma tabela de dados de fatura denominada Trans_Cp. Usando esses dados, você precisa para calcular um total acumulado dos valores da fatura:

Número_Fornecedor Nome_Fornecedor Cidade_Fornecedor Número_Fatura Data_Fatura Valor_Fatura Quantidade Custo_Unidade
11663 Indústrias Poderosas Belo Horizonte 5981807 2000-11-17 618,30 90 6,87
13808 NOVATECH Atacadista Campinas 2275301 2000-11-17 6705,12 976 6,87
12433 Koro International Itajaí 6585673 2000-11-17 7955,46 1158 6,87

Para calcular esse valor, use o comando GROUP. Dentro de cada interação de GROUP, você:

  1. Calcula o total acumulado até o registro atual.
  2. Extrai o número, o valor, a data e o total acumulado da fatura para uma tabela de resultados.
OPEN Trans_Cp
			
COMMENT define o valor inicial do total acumulado como zero
ASSIGN v_total_acumulado = 0,00

COMMENT itera cada registro da tabela para calcular e extrair o total acumulado
GROUP
  ASSIGN v_total_acumulado = v_total_acumulado + Valor_Fatura
  EXTRACT Número_Fatura, Valor_Fatura, Data_Fatura, v_total_acumulado AS "Total acumulado" TO resultados1
END

Na execução do script, os comandos dentro do bloco de GROUP são processados para cada registro da tabela, do início ao fim da tabela, e o total acumulado é calculado e extraído. Se pudéssemos acompanhar a execução do GROUP, teríamos o seguinte:

Primeira iteração de GROUP: total acumulado = 0,00 + 618,30

O GROUP adiciona o valor da fatura do primeiro registro ao total acumulado inicial de 0,00 e extrai os campos para a tabela de resultados:

Número_Fornecedor Nome_Fornecedor Cidade_Fornecedor Número_Fatura Data_Fatura Valor_Fatura Quantidade Custo_Unidade
11663 Indústrias Poderosas Belo Horizonte 5981807 2000-11-17 618,30 90 6,87
13808 NOVATECH Atacadista Campinas 2275301 2000-11-17 6705,12 976 6,87
12433 Koro International Itajaí 6585673 2000-11-17 7955,46 1158 6,87

Segunda iteração de GROUP: total acumulado = 618,30 + 6705,12

O bloco de GROUP adiciona o valor da fatura do segundo registro ao novo total acumulado de 618,30 e extrai os campos para a tabela de resultados:

Número_Fornecedor Nome_Fornecedor Cidade_Fornecedor Número_Fatura Data_Fatura Valor_Fatura Quantidade Custo_Unidade
11663 Indústrias Poderosas Belo Horizonte 5981807 2000-11-17 618,30 90 6,87
13808 NOVATECH Atacadista Campinas 2275301 2000-11-17 6705,12 976 6,87
12433 Koro International Itajaí 6585673 2000-11-17 7955,46 1158 6,87

Terceira iteração de GROUP: total acumulado = 7323,42 + 7955,46

O bloco de GROUP adiciona o valor da fatura do terceiro registro ao novo total acumulado de 7323,42 e extrai os campos para a tabela de resultados:

Número_Fornecedor Nome_Fornecedor Cidade_Fornecedor Número_Fatura Data_Fatura Valor_Fatura Quantidade Custo_Unidade
11663 Indústrias Poderosas Belo Horizonte 5981807 2000-11-17 618,30 90 6,87
13808 NOVATECH Atacadista Campinas 2275301 2000-11-17 6705,12 976 6,87
12433 Koro International Itajaí 6585673 2000-11-17 7955,46 1158 6,87

Tabela de resultados final

Após o processamento do registro final da tabela pelo GROUP, você terá a seguinte tabela de resultados:

Número_Fatura Valor_Fatura Data_Fatura Total_acumulado
5981807 618,30 2000-11-17 618,30
2275301 6705,12 2000-11-17 7323,42
6585673 7955,46 2000-11-17 15278,88

Processamento de casos diferentes usando GROUP IF

Usando a mesma tabela Trans_Cp acima, agora você precisa calcular os totais acumulados para três tipos de faturas:

  • Valor alto (maior ou igual a 1000,00)
  • Valor médio (entre 100,00 e 1000,00)
  • Valor baixo (menor que 100,00)

O COMANDO GROUP oferece uma estrutura IF/ELSE para processar casos diferentes. Você informa as expressões condicionais a serem testadas. Se um registro for avaliado como verdadeiro, os comandos dentro do bloco serão executados.

Como os casos são testados

Os casos são testados de cima para baixo e um registro pode ser processado por apenas um bloco IF/ELSE. O primeiro caso que for avaliado como verdadeiro para o registro processará esse registro:

  1. Quando o GROUP processa o primeiro registro, testa a primeira condição IF (Valor_Fatura >= 1000). Se a condição for avaliada como verdadeira, o código desse caso será executado e nenhum outro caso será testado.
  2. Se o primeiro caso for avaliado como falso, a próxima condição ELSE IF (Valor_Fatura >= 100) será testada. Da mesma forma, se esse teste for avaliado como verdadeiro, o código desse caso será executado e nenhum outro caso será testado.
  3. Finalmente, se nenhum dos casos IF ou ELSE IF for avaliado como verdadeiro, o caso padrão no bloco ELSE processará o registro.

Nota

Se um registro for avaliado como verdadeiro em mais de um caso, será processado apenas pelo primeiro bloco IF/ELSE testado. Os registros nunca são processados por mais de um bloco IF/ELSE em um comando GROUP.

OPEN Trans_Cp

COMMENT define valores iniciais para os totais acumulados
ASSIGN v_total_acumulado_alto = 0,00
ASSIGN v_total_acumulado_medio = 0,00
ASSIGN v_total_acumulado_baixo = 0,00

COMMENT usa GROUP IF para executar comandos ASSIGN e EXTRACT diferentes, dependendo do valor da fatura
GROUP IF Valor_Fatura >= 1000
  ASSIGN v_total_acumulado_alto = v_total_acumulado_alto + Valor_Fatura
  EXTRACT Número_Fatura, Valor_Fatura, Data_Fatura, v_total_acumulado_alto AS "Total acumulado" TO resultados_alto
GROUP IF Valor_Fatura >= 100
  ASSIGN v_total_acumulado_medio = v_total_acumulado_medio + Valor_Fatura
  EXTRACT Número_Fatura, Valor_Fatura, Data_Fatura, v_total_acumulado_medio AS "Total acumulado" TO resultados_medio
ELSE
  ASSIGN v_total_acumulado = v_total_acumulado_baixo + Valor_Fatura
  EXTRACT Número_Fatura, Valor_Fatura, Data_Fatura, v_total_acumulado_baixo AS "Total acumulado" TO resultados_baixo
END

Quando o script é executado, o comando GROUP testa o valor da fatura de cada registro. Dependendo do valor, o registro será usado para atualizar um dos três totais acumulados (alto, médio, baixo), gerando três tabelas de resultados.

LOOP dentro de um GROUP

Ao usar GROUP para processar registros de uma tabela, você pode usar um comando LOOP para executar diversos comandos várias vezes em um único registro. O LOOP é uma segunda iteração dentro da iteração de GROUP e é executado até que uma condição de teste especificada seja avaliada como falsa.

Usando LOOP para dividir um campo

Você tem a seguinte tabela com dados de fatura e precisa isolar informações específicas para valores de fatura por departamento. Uma fatura pode ser relacionada a mais de um departamento, e os códigos de departamento são armazenados em formato delimitado por vírgulas na tabela:

Número_Fornecedor Número_Fatura Data_Fatura Valor_Fatura Código_Departamento
11663 5981807 2000-11-17 618,30 CCD,RDR
13808 2275301 2000-11-17 6705,12 CCD
12433 6585673 2000-11-17 7955,46 CCD,LMO,RDR

Para extrair os valores de fatura por departamento, você:

  1. Usa um comando GROUP para processar a tabela registro a registro.
  2. Calcula o número de departamentos (n) associados a cada registro.
  3. Usa o comando LOOP para iterar o registro n vezes para extrair dados de cada departamento associado ao registro.

Nota

Você precisa incrementar a variável v_contador dentro de LOOP. Caso contrário, o teste WHILE será sempre avaliado como verdadeiro e o script entrará em um loop infinito. É possível incluir um comando SET LOOP nos scripts para evitar loops infinitos. Para obter mais informações, consulte Comando SET.

 

COMMENT
Usa GROUP para contar vírgulas em cada campo de código de departamento como forma de identificar quantos departamentos estão associados ao registro
Executa LOOP em cada registro para cada código do campo, extraindo cada código em seu próprio registro
END
GROUP
  v_quantidade_departamentos = OCCURS(Código_Departamento;',')
  v_contador = 0
  LOOP WHILE v_contador <= v_quantidade_departamentos
    v_depto = SPLIT(Código_Departamento; ','; (v_contador + 1))
    EXTRACT FIELDS Número_Fatura, Valor_Fatura, v_depto AS "Departamento" TO resultado1
    v_contador = v_contador + 1		
  END
END

Na execução do script, os comandos dentro do bloco de GROUP são processados para cada registro da tabela, do início ao fim da tabela. Para cada registro, o comando LOOP itera o registro uma vez por código departamento na lista delimitada por vírgulas e extrai um registro. Se pudéssemos acompanhar a execução do GROUP e do Loop, teríamos o seguinte:

Primeira iteração de GROUP: 2 iterações de LOOP

Número_Fornecedor Número_Fatura Data_Fatura Valor_Fatura Código_Departamento
11663 5981807 2000-11-17 618,30 CCD,RDR
13808 2275301 2000-11-17 6705,12 CCD
12433 6585673 2000-11-17 7955,46 CCD,LMO,RDR

Para o primeiro registro na tabela, o valor de v_quantidade_departamentos é 1. Portanto, LOOP itera duas vezes:

  1. Para a primeira iteração do LOOP:
    • v_contador = 0
    • v_depart = CCD

    O registro a seguir é extraído e o valor de v_contador é incrementado para 1. Portanto, LOOP itera novamente:

    5981807618,30CCD
  2. Para a segunda interação do LOOP:
    • v_contador = 1
    • v_depart = RDR

    O registro a seguir é extraído e o valor de v_contador é incrementado para 2. Portanto, LOOP itera novamente e GROUP prossegue para o próximo registro:

    5981807618,30RDR

Segunda iteração de GROUP: 1 iterações de LOOP

Número_Fornecedor Número_Fatura Data_Fatura Valor_Fatura Código_Departamento
11663 5981807 2000-11-17 618,30 CCD,RDR
13808 2275301 2000-11-17 6705,12 CCD
12433 6585673 2000-11-17 7955,46 CCD,LMO,RDR

Para o segundo registro na tabela, o valor de v_quantidade_departamentos é 0. Portanto, LOOP itera uma vez:

  • v_contador = 0
  • v_depart = CCD

O registro a seguir é extraído e o valor de v_contador é incrementado para 1. Portanto, LOOP itera novamente e GROUP prossegue para o próximo registro:

2275301 6705,12 CCD

Terceira iteração de GROUP: 3 iterações de LOOP

Número_Fornecedor Número_Fatura Data_Fatura Valor_Fatura Código_Departamento
11663 5981807 2000-11-17 618,30 CCD,RDR
13808 2275301 2000-11-17 6705,12 CCD
12433 6585673 2000-11-17 7955,46 CCD,LMO,RDR

Para o terceiro registro na tabela, o valor de v_quantidade_departamentos é 2. Portanto, LOOP itera três vezes:

  1. Para a primeira iteração do LOOP:
    • v_contador = 0
    • v_depart = CCD

    O registro a seguir é extraído e o valor de v_contador é incrementado para 1. Portanto, LOOP itera novamente:

    65856737955,46CCD
  2. Para a segunda interação do LOOP:
    • v_contador = 1
    • v_depart = LMO

    O registro a seguir é extraído e o valor de v_contador é incrementado para 2. Portanto, LOOP itera novamente:

    65856737955,46LMO
  3. Para a terceira iteração do LOOP:
    • v_contador = 2
    • v_depart = RDR

    O registro a seguir é extraído e o valor de v_contador é incrementado para 3. Portanto, LOOP itera novamente e GROUP prossegue para o próximo registro:

    65856737955,46CCD

Tabela de resultados final

Depois que GROUP processou cada registro da tabela e LOOP iterou por todos os códigos de departamento, você terá a seguinte tabela de resultados:

Número_Fatura Valor_Fatura Departamento
5981807 618,30 CCD
5981807 618,30 RDR
2275301 6705,12 CCD
6585673 7955,46 CCD
6585673 7955,46 LMO
6585673 7955,46 RDR