最小値・最大値、抽出処理、結合(join)、コントロールブレーク、併合処理(マージ)、整列処理(外部ソート)
順編成ファイルを順アクセスで読込み、典型的な処理をするアルゴリズムを列挙します。
このような処理は、定例的な事務処理で多く用いられ、歴史的にはCOBOLやPL/Iなどの言語が広く用いられていましたが、現在ではデータベース用の言語が用いられるようになりました。それらは非手続言語でアルゴリズムの説明には不適切です。また、スクリプト言語では、このような処理を重視していません。
そのため、ここでは疑似言語を用います。
これらの処理では、ファイルのレコードを読み終わった(end of file, EOF)ことをプログラムに知らせる方法が言語によりまちまちです。
COBOL: READ ファイル AT END ~ で、終了時の処理を記述します。
C: 自動的に予約語 EOF を true にします。
Java:読み込む場所(文字列変数)を null にします。
のようにまちまちです。そのため、ここの疑似言語では、変数 EOF を true/false にする手段は省略して、
ファイルにレコードが残っている状態を EOF=false, 読み終わった状態を EOF = true
であるとします。
個々のプログラムによる個別処理の部分は、ここではサブルーチンとして記述することにしており、そのサブルーチンを省略しています。サブルーチンをメインルーチンの呼出個所(call命令)に埋め込んでもかまいません。
最小値 = HIGH_VALUE // 言語の持つ最大値 最大値 = LOW_VALUE call ファイル読込み // 比較項目はレコードのフィールド while (EOF == false){ if (比較項目 < 最小値) 最小値 = 比較項目 if (比較項目 > 最小値) 最大値 = 比較項目 call ファイル読込み } call 最小大値の出力
call ファイル読込みを最初と whileループの最後に記述することがポイントです。
call ファイル読込み while (EOF == false){ call 抽出条件 // 条件を満足・不満足で true/false if (抽出条件 == true) { call 抽出レコード(読み込んだレコード)の処理 } call ファイル読込み }
例えば、順編成の売上ファイルのフィールドには商品コードはあるが商品名はありません。商品名は商品コードを主キーとする直接アクセスファイル(あるいはデータベース)の商品マスタファイルにあり、両ファイルの商品コードをキー項目として結合して、売上ファイルに商品名を取り込む処理です。
call 売上ファイル読込み while (EOF == false){ call マスタ照合処理(売上・商品コード == マスタ・商品コード) // 一致したか否かで 照合結果 = true/false if (照合結果 == true) { call 照合成功時処理 // マスタに商品コードが存在したときの処理 } else { call 照合失敗時処理 // マスタに商品コードが存在しないときの処理 } call ファイル読込み }
ファイルは、事前にレコードのフィールドにある小計キーでソート(昇順でも降順でもよい)してあるものとします。
次のような出力になります。
明細
明細
小計
明細
小計
総計
総計累計項目 = 0
call ファイル読込
while (EOF != true) {
前小計キー = 小計キー
小計累計項目 = 0
while (中計キー == 前中計キー) {
call 明細行処理
call ファイル読込
}
call 小計処理
総計累計項目 = 総計累計項目 + 小計累計項目
}
call 総計処理
総計累計項目 = 0
call ファイル読込
while (EOF != true) {
前中計キー = 中計キー
中計累計項目 = 0
while (中計キー == 前中計キー) {
前小計キー = 小計キー
小計累計項目 = 0
while ((中計キー == 前中計キー) and (小計キー == 前小計キー)) {
call 明細行処理
小計累計項目 = 小計累計項目 + 明細累計項目
call ファイル読込
}
call 小計処理
中計累計項目 = 中計累計項目 + 小計累計項目
}
call 中計処理
総計累計項目 = 総計累計項目 + 中計累計項目
}
call 総計処理
最も深いネストに call ファイル読込 を置くことがポイントです。
2つの順編成ファイル、AファイルとBファイルがあり、それぞれ大小を比較するキー、AキーとBキーの昇順にソートしてあります。このA、Bのファイルを読み、比較キーの小さい順にCファイルに出力します。なお、ファイル読込みでは、A・Bファイルのレコードがなくなったとき、Aキー、Bキーの値を HIGH_VALUE に設定することにします。→参照:マージ(併合)
call Aファイル読込み call Bファイル読込み while ((Aキー != HIGH_VALUE) and (Bキー != HIGH_VALUE)) { if (Aキー < Bキー) { call Cファイル出力(A) // Aファイルの内容をCファイルに書き出す call Aファイル読込み } else if (Aキー > Bキー) { call Cファイル出力(B) // Bファイルの内容をCファイルに書き出す call Bファイル読込み } else // Aキー == Bキー のとき call Cファイル出力(A) call Aファイル読込み call Cファイル出力(B) call Bファイル読込み } }
AファイルをAキー項目の昇順にソートします(元のAファイルの内容は保存されません)。ワークファイルとして、BファイルとCファイルを用います。
大きく分割フェーズとマージフェーズの繰り返しでソートします。 外部ソート
分割フェーズ
マージフェーズ
while (ソート完了 == false) Aファイルを入力、B・Cファイルを出力ファイルに指定 前Aキー = HIGH_VALUE ワークファイル = "B" call Aファイル読込み ソート完了 = true while (Aキー != HIGH_VALUE) { if (Aキー < 前Aキー ) { // 連が切れたので分割処理を行う ソート完了 = false call ワークファイルの変更 } call ワークファイル書込み(Aのレコード) call Aファイル読込み } if (ソート完了 == false) { // マージ処理 Aファイルを出力、B・Cファイルを入力ファイルに指定 call マージ処理 // BファイルとCファイルをマージしてAファイルを作成 } }