こんにちは、ふたたびUSP MAGAZINE編集長のまつうらです。昨日は風が炸裂してましたけど、爆弾低気圧って呼ぶんですね。ニュースの題名を見た時は「テロでも起こったか!?」とびっくりしました。
さて、その1、その2に続き、OSC 2012 Tokyo/Springでのセッションの続きとするつもりだったのですが、書いているうちにだいぶその中で語られていたネタから逸脱してしまったので、フツーに行きます。でも、その2で語らなかったJOINの話です。
INNER JOIN(内部結合)といえば、SQLをかじったりすれば必ず登場する概念。そのINNER JOINをするコマンドが古くからUNIXに存在する(POSIX標準である)のを知っていますか? ―「知らない」 じゃあ、UNIX系OSのターミナル用意して試してみましょう。
まずは、会員番号とそれに対する名前を紐付けたファイルとして次のようなもの(members.txt)を用意しておきます。
1 aaaさん 2 bbbさん 3 cccさん 4 dddさん 5 eeeさんそれから、その会員がいくら購入したかを記録しているポイント表(points.txt)も用意しておきます。ただし、会員番号4のdddさんはポイント未獲得ということにして、記録(dddさん用の行)がまだ存在しないようにしておきましょう。
1 10ポイント 2 20ポイント 3 30ポイント 5 50ポイントここまでできたら、あとはこことかこことかに書いてあるjoinコマンドの使い方を見ながら「名前に対応するポイント」を作成してみましょう。
$ join -1 1 -2 1 members.txt points.txt 1 aaaさん 10ポイント # [↑注] 2 bbbさん 20ポイント # 左表(-1)の1列目と、右表(-2)の1列目を 3 cccさん 30ポイント # キーとする 5 eeeさん 50ポイントとご覧の通りなわけですよ(会員番号が邪魔ならさらにパイプでAWKに渡し、2列目,3列目だけ表示させればよい)。一方、ポイント表に未登録な人が誰なのか(すなわちdddさん)を知りたいならば、"-v 1"という具合にオプションを付ければ出てきます。
$ join -1 1 -2 1 -v 1 members.txt points.txt 4 dddさん # [↑注]"-v"オプションで左表(1)にしか無かった行を表示これの右隣に"0ポイント"と追記して(AWKコマンドを使えば簡単)、最初のjoinコマンドの出力結果とくっつければ(SQL的に言うならUNION)、LEFT JOIN相当のことだってできてしまいます。こうして見ると、USP研究所が考案するまでもなくUNIXシェルは、テキストファイルでリレーショナルデータベース処理をやることを想定していたことがわかります。joinコマンドの存在がその証拠です。さらに勘を働かせば、UNIX自体それに向くような設計になっていると気づくことでしょう。
ということで、UNIXは既にJOINの機能を持っています。でもご覧の通り、Open usp TukubaiはJOIN系のコマンドを5つ(後述の表1)もわざわざ独自に提供しています。なぜ作り直したかということは後回しにして、さっそくやってみましょう。最初のJOINの例と同じく、まずはポイント表に登録されている人だけ表示してみます。
$ join1 key=1 members.txt points.txt 1 aaaさん 10ポイント # [↑注] 2 bbbさん 20ポイント # keyは、右表で見る列番号を示す。 3 cccさん 30ポイント # (左表に関しては1列目固定) 5 eeeさん 50ポイントでは次に、ポイント登録の無いdddさんも含まれるようにするにはというと、こんなふうに書きます。
$ loopj "-d0ポイント" num=1 members.txt points.txt 1 aaaさん 10ポイント # [注1]loopjコマンドはFULL JOIN(完全外部結合)に相当 2 bbbさん 20ポイント # [注2]"-d"で始まるオプションで文字列を指定すると 3 cccさん 30ポイント # 行が存在しなかった表にその文字列が埋込まれる。 4 dddさん 0ポイント # [注3]numオプションは、各表の1列目から何列目までを 5 eeeさん 50ポイント # 結合用に見るかを指定する(「何列目を」ではない)こうして、元のjoinコマンドでは簡素に書けなかったLEFT JOIN相当の処理が1行で書けるようになるのです。
ここでTukubaiが提供するJOIN系コマンドをまとめておきます。
機能 | Tukubaiコマンド名 |
---|---|
INNER JOIN (内部結合) |
join1(またはjoin0) |
LEFT JOIN (左外部結合) |
なし(FULL JOIN相当のloopjで代用するか、 表を左右に入れ替えてRIGHT JOIN相当のjoin2で代用) |
RIGHT JOIN (右外部結合) |
join2 |
FULL JOIN (完全外部結合) |
loopj |
直交表作成 | loopx |
これらTukubaiのコマンドを見てると、きっと鼻につくことがあるでしょう。
元々のjoinコマンドは、オプションを駆使すれば確かにいろいろなことが出来ます。オプションだけでできなくても(例えば前述のLEFT JOIN)、コマンドを複数回使えば一応はできます。でも、使用頻度の高い処理が簡素に書けなければ使ってられないわけです。
Tukubaiというコマンドセットが提供する機能は、一見歯抜けに見えますが、実際使ってみると9割、いや、それ以上の割合でその使い方に収まります。なにせTukubaiは、そういうことを試行錯誤しながら仕様を洗練させていったのですから。きっと、使い出したら中毒になりますよ。:-)