n対nマッチングのロジック(C#のサンプルコード付き)

以前に、以下の記事にて、マッチング処理のロジックについて書かせていただきました。
マッチング処理のロジック – サイゼントの技術ブログ

以前の記事では1対1マッチングと1対nマッチングについて説明しました。
今回の記事では、より複雑なn対nマッチングについて補足します。

1対1マッチングは、マスタデータの1つのキー項目に対して、トランザクションデータの0~1つのレコードが対応するものでした。
1対nマッチングは、マスタデータの1つのキー項目に対して、トランザクションデータの0~複数のレコードが対応するものでした。
n対nマッチングは、マスタデータ側も1つであるとは限らず、トランザクションデータの1つのキー項目に対して、マスタデータの0~複数のレコードが対応するケースもある、というものを指します。

n対nマッチングでは、以前に参照したトランザクションデータのレコードが、再び参照される可能性があります。
ファイルに対してランダムにアクセスすることでこれを実現できますが、処理が複雑になるため、今回はファイルは順次読み込みのままで、読み込んだトランザクションデータのレコードを一時的に退避するロジックを提示します。

フローチャートと例は以下の通りとなります。
また、この記事に限りませんが、ソースコードをコピペする場合は、「[」を「[」、「]」を「]」、「>」を「>」、「<」を「<」、「&」を「&」に変換するようにお願いします。

【フローチャート】

【例】

・要件

商品名が管理されている商品マスタと、商品の販売履歴(トランザクション)をファイル形式で読み込み、商品名と販売日を別ファイルで出力したい。

・商品マスタのフォーマット

カンマ区切りの固定長ファイル。
商品コードと商品副コードでレコードを一意に特定できるようにデータをセットする。

・販売履歴のフォーマット

カンマ区切りの固定長ファイル。
商品コード・販売日でレコードを一意に特定できるようにデータをセットする。

・出力ファイルのフォーマット

・プログラムのフォルダ構成

・ソースコード(execute.bat)

・ソースコード(matching.cs)

・商品マスタのレコード(files\master.csv)

・販売履歴のレコード(files\transaction.csv)

・バッチ実行結果(標準出力)

・バッチ実行結果(files\matched.csv)


あけましておめでとうございます!
お久しぶりです。

去年は慌ただしかったので記事を書けずにいましたが、要望があり、再びブログを更新することにしました。
ブログ以外の執筆活動もあるため不定期の更新になりそうですが、折を見て更新を続けていきたいと思います。

改めまして、よろしくお願いします。

ソースコードの重複の排除を関数で学ぶ

「ソースコードから重複を排除して保守性を高める」という考え方は、実務で良いコードを書く上で重要な考え方です。
この考え方が身に付かない内はオブジェクト指向の理解も不十分になるのですが、いきなりオブジェクト指向から入るとこの考え方の重要性がわかりにくくなることがあります。

そこで、ソースコードから重複を排除することの意義を、関数の使い方から学ぶことが有効になることがあります。

今回は、関数を使うことでソースコードから重複を排除し、保守性が高まる例を挙げていきたいと思います。
(サンプルコードはJavaで記述します)


今回のサンプルコードでは、複数の商品の販売価格を計算します。
まずは関数を使わないサンプルコードから書いていこうと思います。

【サンプルコード(関数未使用・修正前)】

・FunctionTestMain.java

【実行結果】


先ほどのソースコードに対して、「店舗独自の割引額を考慮する」という修正を入れていきます。

関数を使用しない場合、割引額(discountRate)を掛けるという修正を複数個所に入れることになります。
これが、ソースコードに重複が発生している状態です。

ソースコードに重複が発生していると、一部だけ修正を漏らすことによるバグに繋がりやすくなります。
このバグを潰すために、テストする範囲も広がってしまいます。

【サンプルコード(関数未使用・修正後)】

・FunctionTestMain.java

【実行結果】


次に、ソースコードを一旦修正前の状態に戻して、関数を入れていきます。

販売額を計算する関数(salesPriceCalc)を入れることで、ソースコードから重複を取り除くことができています。

【サンプルコード(関数使用・修正前)】

・FunctionTestMain.java

【実行結果】


関数を使用したソースコードに対して、先ほどと同じように割引額を考慮する修正を入れます。

重複が関数により排除されているので、割引額を入れる修正は1カ所で済んでいます。
修正箇所が減っているため、修正漏れを心配する必要がなくなり、ソースコードの保守が容易になっています。
言い換えると、時間をかけずにバグが出にくい修正を行うことができるようになります。
修正が繰り返される実務のソースコードでは、これは重要なことです。

【サンプルコード(関数使用・修正後)】

・FunctionTestMain.java

【実行結果】


今回解説したことは、実際の新人研修でも教えることが多いです。
このような簡単な例を用いることで、ソースコードの重複の排除について、わかりやすく説明することができます。


ところで、突然の発表なのですが、このブログでの私の記事はこれが最後となります。
このブログの記事を読んだことがある、と意外な所から声をかけていただくこともあり、大変嬉しく思っています。
少しでも皆様のお役に立てていたのであれば幸いです。

今まで記事を読んでいただき、ありがとうございました!

COBOLのマッチング処理をC#で実装する

COBOLで使われているテクニックは過去のもののように思われがちですが、現在でもちょっとしたツールを作る時に役立ちます。
WindowsOS環境の場合は、ちょっとしたツールはC#で作るのが便利なので、今回はC#でCOBOLのマッチング処理を実装してみました。

今回は、下記の記事を参考に実装しています。
マッチング処理のロジック – サイゼントの技術ブログ

HIGH-VALUEを使う代わりにEOFを示すフラグ変数を使用しているので、その分だけ処理が複雑になっていることには注意してください。
また、この記事に限りませんが、ソースコードをコピペする場合は、「[」を「[」、「]」を「]」、「>」を「>」、「<」を「<」に変換するようにお願いします。

【フォルダ構成】

【ソースコード】

・execute.bat

・matching.cs

【実行前のファイル】

・files\master.csv

・files\transaction.csv

【実行結果】

execute.batをダブルクリックして実行する。

・files\matched.csv

・標準出力


Windows OSで作業や運用を行う場合は、C#を使いこなせると何かと便利です。
C#でツールを使う時に便利なソースコードは、これからも公開していきたいと思います!

文字コードの入門

この記事では、文字コードに関する初歩的な内容について簡単に書いていきます。

1.文字コードの概念とコード体系

コンピューターで取り扱う文字には、それぞれコードが割り振られています。
コードは1~4バイトの情報として取り扱われ、1バイトの文字は1バイト文字、2~4バイトの文字はマルチバイト文字と呼ばれます。
原則として、半角英数字記号は1バイト文字として扱われ、それ以外の文字はマルチバイト文字として扱われます。
(ここでは詳しく触れませんが、半角カナや人間には読めない制御文字は、1バイト文字のこともあればマルチバイト文字のこともあります)
これらの情報は、16進数で表現されることが多いです。また、プログラム上では、10進数で表現されることも多いです。

どの文字にどのコードが割り振られるのかは、コード体系によって決まります。

1バイト文字に関しては、今日のPCではASCIIというコード体系が使われます。
ASCIIにて、どの文字にどのコードが割り振られているのかは、以下の表から確認することができます。
(例えば、「A」には「0x41」(10進数で「65」)が、「a」には「0x61」(10進数で「97」)が割り振られています)
https://ja.wikipedia.org/wiki/ASCII

また、ホストコンピューターでは、1バイト文字にEBCDICという別のコード体系が使われます。
EBCDICの表は以下の通りであり、ASCIIとは異なる割り振られ方をしていることがわかります。
(例えば、「A」には「0xC1」(10進数で「193」)が割り振られています)
https://ja.wikipedia.org/wiki/EBCDIC

マルチバイト文字については、今日ではUTF-8やShiftJISといったコード体系が使われることが多いです。
(マルチバイト文字に関しては、この記事では詳細を割愛します)

2.ソースコード上で文字コードを取り扱う例

ソースコード上でも、文字コードを取り扱うことができます。
と言うより、文字は内部的には文字コードであり、「A」や「a」といった表示は人間が読みやすいように表現しているものです。

以下は、「A」や「a」といった文字が内部的にどのような文字コードを持っているのかを表示するJavaのプログラムです。
ASCIIコード表通りの文字コードが割り振られていることを確認できます。

■ソースコード

・CharCode1.java

■実行結果

また、文字の比較も、文字コードにより行うことができます。
以下は、「ABC」という文字列を前から1文字ずつ読み込み、「B」の文字を読みこんだ時だけ表示を行うJavaのプログラムです。

■ソースコード

・CharCode2.java

■実行結果

3.文字コードを意識する理由

ここで、「なぜプログラミングで文字コードを意識する必要があるのか」と疑問を持った方もいらっしゃるかもしれません。
確かに、人間には読みにくい文字コードを使ったプログラミングをするよりも、文字を直接使ったプログラミングの方が望ましいように思えます。
例えば、この記事で2つ目に取り上げたソースコード(CharCode2.java)では、文字コードを使用しなくても文字コードを使った時のような制御を実現でき、それならば文字コードを使った制御をしない方が望ましいように思えます。

それでも文字コードを意識する一番の理由は、バイナリの制御文字を取り扱うために必要だからです。
文字には、人間が読める文字の他に、コンピューターに命令を送るための制御文字が存在します。
多くの人にとって一番馴染みがある制御文字の一つが「改行文字」です。
コンピューターが改行文字を読みこむと、文章の改行が行われます。
(この記事が正しく改行されて読みやすくなっているのも、この「改行文字」のおかげです)
改行文字はOSによって割り振られている文字コードが異なりますが、Unix/Linuxの場合は「10」が割り振られています。
この文字は、プログラム上で”A”や”a”といった形で記述することができず、プログラミング言語やライブラリでサポートされない場合は、文字コードを参照しないと改行文字であるか否かを判定できません。

例えば、Javaで絵文字を含む文字列を1文字ずつ切り取る場合に、文字コードの参照が必要になります。
解説やコード例は以下の記事に書いています。
java:Unicodeの絵文字をjavaで取り扱う


いかがでしたでしょうか。

文字コードについてプログラミングの入門書に書かれていることは少ないですが、実務では度々目にします。
実務でプログラミングをするのであれば、文字コードについても早めに勉強しておくことをお勧めします。

SQL_select文の結果の結合等(集合演算子)

今回は、select文の結果を結合する文法の紹介です。
結果を結合するためには、集合演算子のUNION(重複排除したい場合はUNION ALL)を用います。
運用作業やプログラミングで複数のselect文の結果を1回のSQL文発行で取得したいことがあるので、知っておくと便利です。

ついでに、UNIONやUNION ALL以外の集合演算子についても紹介します。

【文法】

※集合演算子には以下のようなものがある

・UNION

前後のselect文の結果を結合する。
重複する結果は1行にまとめられる。

・UNION ALL

前後のselect文の結果を結合する。
重複する結果はまとめられない。

・MINUS、EXCEPT

前のselect文の結果から後のselect文の結果を取り除く。
OracleはMINUS、それ以外はEXCEPTを用いる。
(MySQLではサポート外)

・INTERSECT

前のselect文の結果と後のselect文の結果で一致するものだけを抽出する。
(MySQLではサポート外)

※「order by」は個別のselect文にはかからず、集合演算子で結合した結果全体にかかる。

【対象テーブル例】

・A支店商品

・B支店商品

【使用例】

・UNION

・UNION ALL

・MINUS(EXCEPT)

・INTERSECT


いかがでしたでしょうか。

今回は、UNIONに代表される集合演算子について記事を書きました。
何回かに分けて基本的なSQLの書き方に関する記事を書いてきましたが、これが最後になります。
これまで書いてきた文法は何れも実務では頻出なので、運用作業に携わっている人は特に覚えておいた方が良いものばかりです。知らない・使い方があやふやな文法があれば、これを機に覚えることをお勧めします。

これからも、様々な角度から役に立つ記事を書いていきたいと思います!