Exemplo de loop: agregação de dados (DataStage®)

É possível usar o estágio Transformer para incluir informações agregadas às linhas de saída.

Operações de agregação usam um cache que armazena linhas de entrada. É possível monitorar o número de entradas no cache, configurando um nível de limite na guia Variável de loop da janela Propriedades do estágio. Se o limite for atingido quando a tarefa for executada, um aviso será emitido no log e a tarefa continuará sendo executada.

Este cenário é implementado armazenando as linhas agrupadas em um cache de linha de entrada e processando-as quando o valor mudar em uma coluna de chave. No exemplo, as linhas agrupadas são processadas quando o valor na coluna denominada Col1 muda de 1000 para 2000. Duas funções, SaveInputRecord() e GetSavedInputRecord(), são usadas para incluir linhas de entrada para o cache e recuperá-las. SaveInputRecord() é chamado quando uma variável de estágio é avaliada e retorna a contagem de linhas no cache (começando em 1 quando a primeira linha é incluída). GetSavedInputRecord() é chamado quando uma variável de loop é avaliada.

Para implementar esse cenário no estágio Transformer, faça as configurações a seguir:

Variável de estágio
Defina as variáveis de estágio a seguir:
NumSavedRows
SaveInputRecord()
IsBreak
LastRowInGroup(inlink.Col1)
TotalPrice
IF IsBreak THEN SummingPrice + inlink.Price ELSE 0
SummingPrice
IF IsBreak THEN 0 ELSE SummingPrice + inlink.Price
NumRows
IF IsBreak THEN NumSavedRows ELSE 0
Condição de loop
Insira a expressão a seguir como a condição de loop:
@ITERATION <= NumRows
O loop continua iterando para a contagem especificada na variável NumRows.
Variáveis de Loop
Defina a variável de loopa seguir:
SavedRowIndex
GetSavedInputRecord()
Metadados e derivações do link de saída
Defina as colunas do link de saída e suas derivações:
  • Col1 - inlink.Col1
  • Col2 - inlink.Col2
  • Preço- inlink.Price
  • Porcentagem- (inlink.Price * 100)/TotalPrice

SaveInputRecord() é chamado na primeira Variável de estágio (NumSavedRows). SaveInputRecord() salva a linha de entrada atual no cache e retorna a contagem de registros atualmente no cache. Cada linha de entrada em um grupo é salva até que o valor de quebra seja atingido. No último valor no grupo, o NumRows é configurado para o número de linhas armazenadas na cache de entrada. A Condição de loop então executa loop o número de vezes especificado por NumRows, chamando GetSavedInputRecord() a cada vez para tornar atual a próxima linha de entrada salva antes de processar novamente cada linha de entrada para criar cada linha de saída. O uso das colunas de link de entrada no link de saída refere-se a seus valores na linha de entrada recuperada atualmente, portanto, mudará em cada loop de saída.

Armazenando em cache as linhas de entrada selecionadas

É possível chamar o SaveInputRecord() dentro de uma expressão, para que as linhas de entrada sejam salvas apenas no cache quando a expressão for avaliada como true.

Por exemplo, é possível implementar o cenário descrito, mas salvar apenas linhas de entrada onde a coluna de preço não é 0. As configurações são as seguintes:

Variável de estágio
Defina as variáveis de estágio a seguir:
IgnoreRow
IF (inlink.Price = 0) THEN 1 ELSE 0
NumSavedRows
IF IgnoreRecord THEN SavedRowSum ELSE SaveInputRecord()
IsBreak
LastRowInGroup(inlink.Col1)
SavedRowSum
IF IsBreak THEN 0 ELSE NumSavedRows
TotalPrice
IF IsBreak THEN SummingPrice + inlink.Price ELSE 0
SummingPrice
IF IsBreak THEN 0 ELSE SummingPrice + inlink.Price
NumRows
IF IsBreak THEN NumSavedRows ELSE 0
Condição de loop
Insira a expressão a seguir como a condição de loop:
@ITERATION <= NumRows
Variáveis de Loop
Defina a variável de loopa seguir:
SavedRowIndex
GetSavedInputRecord()
Metadados e derivações do link de saída
Defina as colunas do link de saída e suas derivações:
  • Col1 - inlink.Col1
  • Col2 - inlink.Col2
  • Preço- inlink.Price
  • Porcentagem- (inlink.Price * 100)/TotalPrice

Este exemplo produz saída similar ao exemplo anterior, mas a agregação não inclui valores de preço de 0, e nenhuma linha de saída com um valor de preço de 0 é produzida.

Produzindo linhas geradas adicionais

Este exemplo é baseado no primeiro exemplo, mas, neste caso, deseja-se identificar qualquer linha de entrada onde o Preço seja maior ou igual a 100. Se uma linha de entrada tiver um Preço maior ou igual a 100, um desconto de 25% será aplicado ao Preço e uma nova linha de saída adicional será gerada. O valor Col1 na nova linha tem 1 incluído nele para indicar uma entrada de desconto extra. A linha de entrada original ainda é produzida normalmente. Portanto, qualquer linha de entrada com um Preço maior ou igual a 100 produzirá duas linhas de saída, uma com o preço descontado e uma sem.

Os dados de entrada são mostrados na tabela a seguir:

Col1 Col2 Preço
1000 abc 100.00
1000 def 20.00
1000 ghi 60.00
1000 jkl 20.00
2000 zyx 120.00
2000 wvu 110.00
2000 tsr 170.00
A tabela necessária é mostrada na tabela a seguir:
Col1 Col2 Preço Porcentagem
1000 abc 100.00 50.00
1001 abc 75.00 50.00
1000 def 20.00 10.00
1000 ghi 60.00 30.00
1000 jkl 20.00 10.00
2000 zyx 120.00 30.00
2001 zyx 90.00 30.00
2000 wvu 110.00 27.50
2001 wvu 82.50 27.50
2000 tsr 170.00 42.50
2001 tsr 127.50 42.50

Para implementar esse cenário no estágio Transformer, faça as configurações a seguir:

Variável de estágio
Defina as variáveis de estágio a seguir:
NumSavedRowInt
SaveInputRecord()
AddRow
IF (inlink.Price >= 100) THEN 1 ELSE 0
NumSavedRows
IF AddRow THEN SaveInputRecord() ELSE NumSavedRowInt
IsBreak
LastRowInGroup(inlink.Col1)
TotalPrice
IF IsBreak THEN SummingPrice + inlink.Price ELSE 0
SummingPrice
IF IsBreak THEN 0 ELSE SummingPrice + inlink.Price
NumRows
IF IsBreak THEN NumSavedRows ELSE 0
Condição de loop
Insira a expressão a seguir como a condição de loop:
@ITERATION <= NumRows
O loop continua iterando para a contagem especificada na variável NumRows.
Variáveis de Loop
Defina as variáveis de loop a seguir:
SavedRowIndex
GetSavedInputRecord()
AddedRow
LastAddedRow
LastAddedRow
IF (inlink.Price < 100) THEN 0 ELSE IF (AddedRow = 0) THEN 1 ELSE 0
Metadados e derivações do link de saída
Defina as colunas do link de saída e suas derivações:
  • Col1 - IF (inlink.Price < 100) THEN inlink.Col1 ELSE IF (AddedRow = 0) THEN inlink.Col1 ELSE inlink.Col1 + 1
  • Col2 - inlink.Col2
  • Preço- IF (inlink.Price < 100) THEN inlink.Price ELSE IF (AddedRow = 0) THEN inlink.Price ELSE inlink.Price * 0.75
  • Porcentagem- (inlink.Price * 100)/TotalPrice

O SaveInputRecord é chamado uma ou duas vezes dependendo do valor de Preço. Quando SaveInputRecord é chamado duas vezes, além da agregação normal, ele produz o registro de saída extra com o valor de Preço recalculado. A Variável de loop AddedRow é usado para avaliar os valores da coluna de saída de forma diferente para cada uma das linhas de entrada duplicadas.

Erros de tempo de execução

O número de chamadas para SaveInputRecord() e GetSavedInputRecord() deve corresponder para cada loop. É possível chamar SaveInputRecord() várias vezes para incluir no cache, mas uma vez que você chamar GetSavedInputRecord(), deverá chamá-lo vezes suficientes para esvazar a cache de entrada antes de poder chamar SaveInputRecord() novamente. Os exemplos descritos poderão gerar erros de tempo de execução nas circunstâncias a seguir se esta regra não for observada:

  • Se seu estágio Transformer chamar GetSavedInputRecord antes de SaveInputRecord, um erro fatal semelhante ao exemplo a seguir será relatado no log da tarefa:
    APT_CombinedOperatorController,0: Fatal Error: get_record() called on 
    record 1 but only 0 records saved by save_record()
  • Se seu estágio Transformer chamar GetSavedInputRecord mais vezes do que SaveInputRecord, um erro fatal semelhante ao exemplo a seguir será relatado no log da tarefa:
    APT_CombinedOperatorController,0: Fatal Error: get_record() called on 
    record 3 but only 2 records saved by save_record()
  • Se seu estágio Transformer chamar SaveInputRecord, mas não chamar GetSaveInputRecord, um erro fatal semelhante ao exemplo a seguir será relatado no log da tarefa:
    APT_CombinedOperatorController,0: Fatal Error: save_record() called on 
    record 3, but only 0 records retrieved by get_record()
  • Se seu estágio Transformer não chamar GetSavedInputRecord o número de vez que chamar SaveInputRecord, um erro fatal semelhante ao exemplo a seguir será relatado no log da tarefa:
    APT_CombinedOperatorController,0: Fatal Error: save_record() called on 
    record 3, but only 2 records retrieved by get_record()