分组和循环

GROUP 和 LOOP 命令提供了两种重复执行一系列命令的方式。 GROUP 针对每个记录执行一个或多个命令的单个迭代。 LOOP 针对单个记录执行一系列命令的多个迭代,并且只能在 GROUP 块内部使用。

GROUP 简单示例

您具有一个名为 Ap_Trans 的发票数据表。 使用该数据,您需要计算发票金额的运行合计:

Vendor_Number Vendor_Name Vendor_City Invoice_Number Invoice_Date Invoice_Amount Quantity Unit_Cost
11663 More Power Industries Los Angeles 5981807 2000-11-17 618.30 90 6.87
13808 NOVATECH Wholesale Des Moines 2275301 2000-11-17 6705.12 976 6.87
12433 Koro International Sheveport 6585673 2000-11-17 7955.46 1158 6.87

为了计算该金额,您使用 GROUP 命令。 在 GROUP 的每个迭代内部,您:

  1. 计算截止到当前记录的运行合计。
  2. 将发票编号、金额、日期和运行合计提取至结果表。
OPEN Ap_Trans
			
COMMENT 将运行合计的初始值设置为零
ASSIGN v_running_total = 0.00

COMMENT 对该表中的每个记录进行遍历处理,然后计算并提取运行合计
GROUP
  ASSIGN v_running_total = v_running_total + Invoice_Amount
  EXTRACT Invoice_Number, Invoice_Amount, Invoice_Date, v_running_total AS "Running total" TO results1
END

当该脚本运行时,将从上到下,针对表中的每个记录处理 GROUP 块内部的命令,并且计算和提取运行合计。 如果我们能够在 GROUP 运行时在其中穿行,则会看到以下过程:

GROUP 的第一个迭代:运行合计 = 0.00 + 618.30

GROUP 将第一个记录的发票金额添加到初始运行合计 0.00 并且将域提取至结果表:

Vendor_Number Vendor_Name Vendor_City Invoice_Number Invoice_Date Invoice_Amount Quantity Unit_Cost
11663 More Power Industries Los Angeles 5981807 2000-11-17 618.30 90 6.87
13808 NOVATECH Wholesale Des Moines 2275301 2000-11-17 6705.12 976 6.87
12433 Koro International Sheveport 6585673 2000-11-17 7955.46 1158 6.87

GROUP 的第二次迭代:运行合计 = 618.30 + 6705.12

GROUP 块将第二个记录的发票金额添加到新的运行合计 618.30 并且将域提取至结果表:

Vendor_Number Vendor_Name Vendor_City Invoice_Number Invoice_Date Invoice_Amount Quantity Unit_Cost
11663 More Power Industries Los Angeles 5981807 2000-11-17 618.30 90 6.87
13808 NOVATECH Wholesale Des Moines 2275301 2000-11-17 6705.12 976 6.87
12433 Koro International Sheveport 6585673 2000-11-17 7955.46 1158 6.87

GROUP 的第三次迭代:运行合计 = 7323.42 + 7955.46

GROUP 块将第三个记录的发票金额添加到新的运行合计 7323.42 并且将域提取至结果表:

Vendor_Number Vendor_Name Vendor_City Invoice_Number Invoice_Date Invoice_Amount Quantity Unit_Cost
11663 More Power Industries Los Angeles 5981807 2000-11-17 618.30 90 6.87
13808 NOVATECH Wholesale Des Moines 2275301 2000-11-17 6705.12 976 6.87
12433 Koro International Sheveport 6585673 2000-11-17 7955.46 1158 6.87

最终的结果表

在 GROUP 已处理该表中的最后一个记录后,您将拥有以下结果表:

Invoice_Number Invoice_Amount Invoice_Date Running_total
5981807 618.30 2000-11-17 618.30
2275301 6705.12 2000-11-17 7323.42
6585673 7955.46 2000-11-17 15278.88

使用 GROUP IF 处理不同的情况

使用如上所示的相同 AP_Trans 表,您现在需要计算三个类型的发票的运行合计:

  • 高值(大于或者等于 1000.00)
  • 中值(介于 100.00 和 1000.00 之间)
  • 低值(小于 100.00)

GROUP 命令提供了一个 IF/ELSE 结构以处理不同的情况。 您提供了要测试的条件表达式,并且如果某个记录评估为真,则块内部的命令会运行。

如何测试情况

情况被从上到下进行测试,并且一个记录只能由一个 IF/ELSE 块处理。 对于该记录而言,第一个评估为真的情况是处理该记录的情况:

  1. 当 GROUP 处理第一个记录时,它会根据第一个 IF 条件来测试它 (Invoice_Amount >= 1000)。 如果该条件评估为真,则此情况的代码会运行,并且不会再测试其他情况。
  2. 如果第一个情况评估为假,则会测试下一个 ELSE IF 条件 (Invoice_Amount >= 100)。 同样,如果该测试评估为真,则此情况的代码会运行,并且不会测试其他情况。
  3. 最后,如果 IF 或 ELSE IF 情况中没有一个情况评估为真,则 ELSE 块中的默认情况会处理该记录。

说明

如果某个记录对于一种以上的情况皆评估为真,则该记录只被测试它的第一个 IF/ELSE 块处理。 记录永远不会被 GROUP 命令中一个以上的 IF/ELSE 块处理。

OPEN Ap_Trans

COMMENT 设置运行合计的初始值
ASSIGN v_running_total_hi = 0.00
ASSIGN v_running_total_med = 0.00
ASSIGN v_running_total_low = 0.00

COMMENT 根据发票金额的不同,使用 GROUP IF 运行不同的 ASSIGN 和 EXTRACT 命令
GROUP IF Invoice_Amount >= 1000
  ASSIGN v_running_total_hi = v_running_total_hi + Invoice_Amount
  EXTRACT Invoice_Number, Invoice_Amount, Invoice_Date, v_running_total_hi AS "Running total" TO results_hi
ELSE IF Invoice_Amount >= 100
  ASSIGN v_running_total_med = v_running_total_med + Invoice_Amount
  EXTRACT Invoice_Number, Invoice_Amount, Invoice_Date, v_running_total_med AS "Running total" TO results_med
ELSE
  ASSIGN v_running_total_low = v_running_total_low + Invoice_Amount
  EXTRACT Invoice_Number, Invoice_Amount, Invoice_Date, v_running_total_low AS "Running total" TO results_low
END

当该脚本运行时, GROUP 命令会测试每个记录的发票金额。 根据金额的不同,将使用记录来更新三个运行合计(低、中、高)之一并且生成三个结果表。

GROUP 内部的 LOOP

使用 GROUP 处理表中的记录时,您可以一个使用 LOOP 命令对单个记录多次执行一系列命令。 LOOP 是发生在 GROUP 迭代内部的辅助迭代,它会运行到您指定的测试条件评估为假为止。

使用 LOOP 拆分域

您具有以下包含发票数据的表,并且需要按部门隔离发票金额的特定信息。 一个发票可能与一个以上的部门相关,部门代码以逗号分隔格式存储在该表中:

Vendor_Number Invoice_Number Invoice_Date Invoice_Amount Department_Code
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

要按部门提取发票金额,您:

  1. 使用 GROUP 命令逐个记录地处理该表。
  2. 计算与每个记录相关联的部门的数量 (n)。
  3. 使用 LOOP 命令在该记录上迭代 n 次,以提取与该记录相关联的每个部门的数据。

说明

您必须在 LOOP 内部递增 v_counter 变量。 如果您不这样做,则 WHILE 测试总是评估为真,脚本会进入无限循环。 您可以在您的脚本中包括一个 SET LOOP 命令以防备无限循环。 有关详细信息,请参见SET 命令

 

COMMENT
使用 GROUP 统计每个部门代码字段中的逗号个数,作为识别有多少个部门与该记录相关联的方式
对每个记录执行 "LOOP" 操作以查找该字段中的每个代码,并且将每个代码提取到它自己的记录中
END
GROUP
  v_department_count = OCCURS(Department_Code,',')
  v_counter = 0
  LOOP WHILE v_counter <= v_department_count
    v_dept = SPLIT(Department_Code, ',', (v_counter + 1))
    EXTRACT FIELDS Invoice_Number, Invoice_Amount, v_dept AS "Department" TO result1
    v_counter = v_counter + 1		
  END
END

当该脚本运行时,将从上到下,针对该表中的每个记录处理 GROUP 块内部的命令。 对于每个记录,LOOP 命令都会针对逗号分隔列表中的每个部门代码在该记录上迭代一次,然后提取一个记录。 如果我们能够在 GROUP 和 LOOP 运行时在其中穿行,则会看到以下过程:

GROUP 的第一次迭代:LOOP 的两次迭代

Vendor_Number Invoice_Number Invoice_Date Invoice_Amount Department_Code
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

对于该表中的第一个记录,v_department_count 的值是 1,因此 LOOP 迭代两次:

  1. 对于 LOOP 的第一次迭代:
    • v_counter = 0
    • v_depart = CCD

    以下记录被提取,并且 v_counter 的值被递增至 1,因此 LOOP 再次迭代:

    5981807618.30CCD
  2. 对于 LOOP 的第二次迭代:
    • v_counter = 1
    • v_depart = RDR

    以下记录被提取,并且 v_counter 的值被递增至 2,因此 LOOP 不会再次迭代,并且 GROUP 前进至下一个记录:

    5981807618.30RDR

GROUP 的第二次迭代:LOOP 的一次迭代

Vendor_Number Invoice_Number Invoice_Date Invoice_Amount Department_Code
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

对于该表中的第二个记录,v_department_count 的值是 0,因此 LOOP 迭代一次:

  • v_counter = 0
  • v_depart = CCD

以下记录被提取,并且 v_counter 的值被递增至 1,因此 LOOP 不会再次迭代,GROUP 前进至下一个记录:

2275301 6705.12 CCD

GROUP 的第三次迭代:LOOP 的三次迭代

Vendor_Number Invoice_Number Invoice_Date Invoice_Amount Department_Code
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

对于该表中的第三个记录,v_department_count 的值是 2,因此 LOOP 迭代三次:

  1. 对于 LOOP 的第一次迭代:
    • v_counter = 0
    • v_depart = CCD

    以下记录被提取,并且 v_counter 的值被递增至 1,因此 LOOP 再次迭代:

    65856737955.46CCD
  2. 对于 LOOP 的第二次迭代:
    • v_counter = 1
    • v_depart = LMO

    以下记录被提取,并且 v_counter 的值被递增至 2,因此 LOOP 再次迭代:

    65856737955.46LMO
  3. 对于 LOOP 的第三次迭代:
    • v_counter = 2
    • v_depart = RDR

    以下记录被提取,并且 v_counter 的值被递增至 3,因此 LOOP 不会再次迭代,并且 GROUP 到达该表的末尾:

    65856737955.46RDR

最终的结果表

在 GROUP 处理完该表中的每个记录之后,LOOP 已对所有部门代码进行了迭代,您将拥有以下结果表:

Invoice_Number Invoice_Amount 部门
5981807 618.30 CCD
5981807 618.30 RDR
2275301 6705.12 CCD
6585673 7955.46 CCD
6585673 7955.46 LMO
6585673 7955.46 RDR