分组和循环
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 的每个迭代内部,您:
- 计算截止到当前记录的运行合计。
- 将发票编号、金额、日期和运行合计提取至结果表。
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 块处理。 对于该记录而言,第一个评估为真的情况是处理该记录的情况:
- 当 GROUP 处理第一个记录时,它会根据第一个 IF 条件来测试它 (Invoice_Amount >= 1000)。 如果该条件评估为真,则此情况的代码会运行,并且不会再测试其他情况。
- 如果第一个情况评估为假,则会测试下一个 ELSE IF 条件 (Invoice_Amount >= 100)。 同样,如果该测试评估为真,则此情况的代码会运行,并且不会测试其他情况。
- 最后,如果 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 |
要按部门提取发票金额,您:
- 使用 GROUP 命令逐个记录地处理该表。
- 计算与每个记录相关联的部门的数量 (n)。
- 使用 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 迭代两次:
- 对于 LOOP 的第一次迭代:
- v_counter = 0
- v_depart = CCD
以下记录被提取,并且 v_counter 的值被递增至 1,因此 LOOP 再次迭代:
5981807 618.30 CCD - 对于 LOOP 的第二次迭代:
- v_counter = 1
- v_depart = RDR
以下记录被提取,并且 v_counter 的值被递增至 2,因此 LOOP 不会再次迭代,并且 GROUP 前进至下一个记录:
5981807 618.30 RDR
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 迭代三次:
- 对于 LOOP 的第一次迭代:
- v_counter = 0
- v_depart = CCD
以下记录被提取,并且 v_counter 的值被递增至 1,因此 LOOP 再次迭代:
6585673 7955.46 CCD - 对于 LOOP 的第二次迭代:
- v_counter = 1
- v_depart = LMO
以下记录被提取,并且 v_counter 的值被递增至 2,因此 LOOP 再次迭代:
6585673 7955.46 LMO - 对于 LOOP 的第三次迭代:
- v_counter = 2
- v_depart = RDR
以下记录被提取,并且 v_counter 的值被递增至 3,因此 LOOP 不会再次迭代,并且 GROUP 到达该表的末尾:
6585673 7955.46 RDR
最终的结果表
在 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 |