基本帳票編:顧客別来店回数

本章では、初級コマンドで用いた2002年のデータを用いて、下図に示すような「顧客別来店回数」の帳票を作成する。


出力結果

顧客別来店回数

チュートリアル

顧客 来店回数
A00001 2
A00002 5
A00003 3
A00004 6
A00005 2
A00006 2
A00007 6
A00008 2
A00009 6
A00010 5
A00011 1
A00012 10
A00014 6
A00015 4
A00016 3
A00017 13
A00018 5
A00019 3
A00020 6

処理の流れ

上図の帳票を作成するにあたり、これまでに学習したコマンド以外に必要となるコマンドは、「NULL値を含む行を削除する」コマンドである。
まずは、次に示す回答見ずに、各自で、入力データから、上図の帳票を作成するために、コマンドをどのように組み合わせて実行すればよいか(処理の流れ)を考えてもらいたい。

回答:処理の流れ

  1. 顧客がNULLである行を削除する
  2. 必要な項目「顧客」「日付」を選ぶ
  3. 顧客と日付で行を単一化する
  4. 顧客別行数をカウントし、「来店回数」項目とする
  5. 出力する項目「顧客」、「来店回数」項目を抜き出す

 まず顧客コードがNULLの行を削除するが、これは会員でない顧客の購買履歴を削除することに等しい。ただし、今回利用している人工データでは、全ての購買データは顧客コードを伴っているため、この処理において削除される行はない。
 次に、来店回数の定義について説明する。来店回数を考えるとき、何をもって一回の来店とするかによって三通りの考え方がある。一つは、顧客別のレシート枚数を来店回数と見なすという方法である。しかし、お客さんが一旦精算をすませ、その時にレジ周りにある買い忘れ品に気づき、その場で再び精算をした場合、それぞれの精算におけるレシート番号は異なってくる。レシート枚数を来店回数と見なすと、このようなケースを2回の来店とカウントしてしまう。
 二つ目の方法は、この問題を解決するために、ある顧客が一日に何回きたとしても、それは一回の来店と見なす方法がある。しかし一方で、ある顧客が朝と夜との2回来店したとしても、それは一回の来店として見なされてしまう。
 三つ目の方法は上記二つの方法を組合せ、ある顧客について、ある時間内(例えば5分内)に発生したレシートは同じ来店と見なすという方法である。この方法の欠点は処理が非常に複雑になる点である。
 上記に示した処理の流れは、二つ目の方法に基づいている。一つ目の方法を採用したければ、「日付+レシート番号」でレシートを識別するようにすればよい。ここでレシート番号だけの項目を使うのではなく日付を使うのは、通常、レジのレシート番号は、桁数が限られているために番号を使いまわしており、レシート番号だけを使うと、その番号が重複してしまう可能性があるからである。

次に、上記の「処理の流れ」における1の処理について解説する。

NULL値を含む行を削除する(xtdelnul)

xtdelnul は、-fで指定した項目がNULL("*"で表される)である行を削除する。

上述の処理の流れにおいては、「xtdelnul -f 顧客」と指定すればよい。

スクリプト

以上の説明で、顧客別来店回数を求めるスクリプトを書く準備が整った。以下にその回答を示すが、回答を見る前に各自でチャレンジしてもらいたい。

#!/bin/bash
xtdelnul -f 顧客 -i /mnt/h00/tutorial/dat.xt |
xtcut -f 顧客,日付 |
xtuniq -k 顧客,日付 |
xtcount -k 顧客 -a 来店回数 |
xtcut -f 顧客,来店回数 |
xtheader -l "顧客別来店回数" -c "チュートリアル" -o visit.xt

実行結果は各自で確認してもらいたい。

次に、レシート番号に基づいた来店回数の求め方(来店回数に関する一つ目の定義)のスクリプトを加えて、それら二つを結合するスクリプトを考えて見よう。

上記のスクリプト以降の処理の流れは以下のようになるであろう。

  1. 顧客がNULLである行を削除する
  2. 必要な項目「顧客」「日付」「レシート番号」を選ぶ
  3. 顧客と日付、レシート番号で行を単一化する
  4. 顧客別行数をカウントし、「来店回数2」項目とする
  5. そこに以前に作ったファイルvisit.xtから「来店回数」項目を結合する。
  6. 最後に出力する項目「顧客」、「来店回数」、「来店回数2」の項目を抜き出す

実際のスクリプトは以下のようになるであろう。実行結果は各自で確認してもらいたい。

#!/bin/bash
xtdelnul -f 顧客 -i /mnt/h00/tutorial/dat.xt |
xtcut -f 顧客,日付 |
xtuniq -k 顧客,日付 |
xtcount -k 顧客 -a 来店回数 |
xtcut -f顧客,来店回数 -o xxa

xtdelnul -f顧客 -i /mnt/h00/tutorial/dat.xt |
xtcut -f 顧客,日付,レシート |
xtuniq -k 顧客,日付,レシート |
xtcount -k 顧客 -a 来店回数2 |
xtjoin -k 顧客 -m xxa -f来店回数 |
xtcut -f 顧客,来店回数,来店回数2 |
xtheader -l "顧客別来店回数(2)" -c "チュートリアル" -o visitRec.xt

rm -f xx*

OnePoint ワークファイルについて
 上記のスクリプトの最後の行に「rm -f xx*」の記述があるが、このコマンドによって、カレントディレクトリにおけるxxで始まるファイルが全て削除される(-fパラメータは、一致するファイルがなくてもエラーメッセージを出さない指定である)。上記のスクリプトでは途中でxxaというファイルに途中経過を書き出している。このファイルは最終的には必要なくなるもので、一般的にワークファイルもしくはテンポラリファイルと呼ばれる。
 ワークファイルは時としてサイズが大きくなり、いつまでも残しておくとディスクスペースが浪費されてしまう。またより複雑な処理になると、ワークファイルを複数個利用するケースが出てくる。そこでワークファイルの名称を統一し(例えば頭にxxをつけるなど)、スクリプトの最後にそれらのファイルを消去するようにしておくとよい。

練習課題

次のようなデータを作成しよう。スクリプト名及び結果ファイル名は表に示されたものを使おう。

帳票名 スクリプト名 結果ファイル(xt) 結果ファイル(html)
顧客来店回数ベスト20 visit1.sh visit1.xt visit1.html
月別顧客来店回数ベスト5 visit2.sh visit2.xt visit2.html
スポーツドリンク(細分類が140323)を購入したことのある顧客の来店回数ベスト20 visit3.sh visit3.xt visit3.html