業務システム開発手法の「ユニケージ」では、データベース管理システムやフレームワークなどを使わずにシステムを構築します。システムの中身が見えやすい分、仕組みやルールを理解していないと正しい開発ができません。第4回はSQLの「JOIN」句のようなテーブル結合を紹介します。
業務システムなどでは、リレーショナルデータベース管理システム(RDBMS)内に作成したテーブル上にデータを格納しています。一般的に、同じ物や人などに関連する情報を一つの大きなテーブルで管理しているわけではなく、用途別や属性別に複数のテーブルに分けられて保存されています。
このような場合、ある業務アプリケーションが必要とする情報が複数のテーブルにまたがっている場合もあります。それらの情報を一つにまとめることができれば、アプリケーションからの利用が簡単になります。
このような複数のテーブルを一つにまとめる処理が「テーブル結合」です。ユニケージではデータを管理するのがテーブルではなく、テキストファイルという違いがあるにせよ、テーブル結合は重要な機能です。
テーブル結合には、主に「内部結合」(INNER JOIN)と「外部結合」(OUTER JOIN)の2種類があります。テーブル結合では、結合する二つのテーブル上にある「キー」となる値を使って結合します。キーは、レコード(行)ごとに管理しているデータの識別子となるカラム(列)のデータです。識別子とするため、キーの値はユニーク(唯一無二)でなければいけません。
内部結合では、キーの値で指定した条件に一致するレコードが双方のテーブルに存在する場合、そのレコードを結合して抽出します(図1)。SQLで内部結合を実行する場合、「SELECT」文の中で「INNER JOIN」句を指定します。なお、「INNER」の文字は省略できます。
外部結合は、キーの値で指定した条件に一致するレコードが基準となるテーブルに存在する場合、基準となるテーブル内のレコードを基にして結合・抽出を実施します(図2)。基準としないもう一つのテーブルに、キーの値で指定した条件に一致するレコードがなければ、カラムの値を「NULL」(空)として結合します。
基準となるテーブルが左か右かで外部結合を実行するSQLが異なります。左の場合、SELECT文で「LEFT OUTER JOIN」句を指定します。こうすれば、「FROM」句で指定したテーブルが基準になります。右の場合は「RIGHT OUTER JOIN」句を指定します。こちらはRIGHT OUTER JOINの後に指定したテーブルが基準となります。なお、どちらも「OUTER」の文字は省略できます。
外部結合には「完全外部結合」(FULL OUTER JOIN)もあります。完全外部結合では、条件に一致しないレコードも結合・抽出されます。結合するレコードがない場合、カラムの値はNULLとして結合します。
このほか、内部結合でも外部結合でもない交差結合(CROSS JOIN)もあります。交差結合では、キーに関係なく、双方のテーブル上に存在する各レコードの組み合わせでテーブルを結合・抽出します。
ユニケージの専用コマンド群「usp Tukubai」には、タグ形式で保存されたデータファイルを結合するコマンドとして「tagjoin1」「tagjoin2」「tagloopj」「tagloopx」などが用意されています。内部結合はtagjoin1、外部結合はtagjoin2、完全外部結合はtagloopj、交差結合ではtagloopxが使えます。
なお、いずれのコマンドも次の二つ条件を満たしていないと正しく動作しません。後述するマスタファイルの第1カラムに条件となるキーを配置すること、キーとなるカラムの値が昇順に並んでいることです。昇順に並んでいない場合、usp Tukubaiの「tagmsort」コマンドを使って並べ替えておきます。
tagjoin1、tagjoin2、tagloopj、tagloopxはいずれも、SELECT文の「WHERE」句のように出力するカラムを絞り込んで抽出する機能を備えていません。カラムを絞り込むには、本連載第3回で紹介した「tagself」「tagawk」「tagcond」のコマンドと組み合わせます。ちなみに、SELECT文のように複雑な検索や結合ができるのも便利です。しかし、usp Tukubaiのように各コマンドを単機能にした方がプログラムの可読性が高まり、バグの発生を抑えられます。
それでは、二つのデータファイルを用意し、ユニケージによる内部結合と外部結合を実行していきます。用意した二つのテーブルは図3の「master」ファイル、図4の「tran」ファイルです。masterファイルには「CODE」(社員番号)、「NAME」(名前)、「AGE」(年齢)が、tranファイルには「DATE」(日時)、「CODE」(社員番号)、「AMOUNT」(金額)が格納されています。
ユニケージでは「マスタファイル」と「トランザクションファイル」という言葉でデータファイルの性質を表します。マスタファイルは、結合時や抽出時に参照される名簿や台帳のようなファイルです。トランザクションファイルは、結合や抽出を行う際に基準となるファイルです。
どのキーで結合するのかの「key=カラム名」オプションと、マスタファイル、トランザクションファイルの順にデータファイルをtagjoin1コマンドの引数に指定し、次のように実行すると、内部結合を実行できます。
1 2 3 4 5 6 7 8 9 10 |
$ tagjoin1 key=CODE master tran ↵ DATE CODE NAME AGE AMOUNT 20230401 0000003 杉山 26 200 20230402 0000003 杉山 26 400 20230405 0000003 杉山 26 600 20230401 0000005 崎村 50 250 20230402 0000005 崎村 50 450 20230402 0000007 梶川 42 210 20230404 0000007 梶川 42 410 20230406 0000007 梶川 42 610 |
まず、マスタファイル内に存在するキーの値からトランザクションファイルのレコードを抽出します。抽出したレコードのキーとなるカラムの後に、マスタファイルのレコードを追加して内部結合の処理が完了します。
どのキーで連結するのかの「key=カラム名」オプションと、マスタファイル、トランザクションファイルの順にデータファイルをtagjoin2コマンドの引数に指定し、次のように実行すると、外部結合を実行できます。なお、後に指定したトランザクションファイルが基準となるので左右を入れ換えるには引数に指定するデータファイルの順番を変えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ tagjoin2 key=CODE master tran ↵ DATE CODE NAME AGE AMOUNT 20230401 0000001 _ _ 300 20230403 0000001 _ _ 500 20230404 0000001 _ _ 700 20230401 0000003 杉山 26 200 20230402 0000003 杉山 26 400 20230405 0000003 杉山 26 600 20230401 0000005 崎村 50 250 20230402 0000005 崎村 50 450 20230402 0000007 梶川 42 210 20230404 0000007 梶川 42 410 20230406 0000007 梶川 42 610 |
マスタファイルに存在しない、結合すべきレコードは、カラムの値にNULLとして「_」(アンダーバー)を挿入して結合・抽出します。
今回は、ユニケージでのテーブル結合を紹介しました。実際のユニケージによる開発では何百万レコードにも及ぶデータファイルの結合を実施して帳票などを作成しています。本連載では、SQLとの違いが分かりやすいようにタグ付きのデータファイルを使っていますが、本来のユニケージ開発ではタグなし
のデータファイルが一般的です。よって、usp Tukubaiの「join1」と「join2」といったコマンドを使ってテーブル結合を実施します。
次回は、ユニケージにおける排他制御について説明する予定です。
著者:田渕 智也、高橋 未来哉
※本記事は、シェルスクリプトマガジン Vol.85(2023年8月号)に掲載した記事からの転載です。