\documentstyle[epsf]{jarticle} \title{\LARGE{集計レポート}} \author{牧之内研 M1 龍 浩志} \begin{document} \maketitle \section{集計レポート} データベースでは,問い合わせを行なって目的のデータを検索するという だけでなく,データベースに登録されているデータや検索結果をいろいろな角度 から分析をすることができるようにデータの集計を行なうことができます.例 えば,売り上げテーブルから売り上げの合計を集計する,得意先ごとに売り上げを集計するなどです.そこで,今回はこのような集計結果をレポートする ために必要となる集約関数や問い合わせについて,またJasmineでの例について説明します. \section{集約関数} 複数のタプルを対象として,タプルの数,合計,平均,最大値,最小値といっ た集計値を求める関数を集約関数といいます.SQLでは, \begin{itemize} \item count() \item sum(属性名) \item avg(属性名) \item max(属性名) \item min(属性名) \end{itemize} などがあり,count()はタプルの数を,それ以外は指定した属性について集約値を求めます.さらに, where句の条件を使って絞り込むと,絞り込んだタプルのみを対象として,集 約値を求めることができます. \begin{center} \epsfile{file=syuyaku.eps} \end{center} Jasmineの場合は,count(),sum(),average(),min(),max()という関数が用意さ れています.count()は任意の集合p1に対して, \begin{verbatim} p1.count(); \end{verbatim} として,集合p1の要素数を求めることができますが,その他の関数は数値型の集 合(Integer,Decimal,Real)に対してのみ行なえます. 集合p2=${\{}$50,100,150${\}}$のような数値型の集合に対して, \begin{verbatim} p2.sum(); p2.average(); p2.min(); p2.max(); \end{verbatim} として,各種の集約値を求めることができます. \section{group-by} group-by句は特定の列に同じ値をもつものをまとめて,グループ化を行ないま す.さらに,集約関数を組み合わせて各グループごとの集約値を計算すること ができます.下の図は,売り上げテーブルから商品ごとにグループ化を行ない, 商品ごとの売り上げを求めています.結果は,グループ化した属性と集約値の 2つの列となります. \begin{center} \epsfile{file=group.eps} \end{center} Jasmineで記述する場合, \begin{verbatim} > Bag<[Integer CommodityNo,Integer TotalSales]> g; \end{verbatim} (グループ化する属性,集約した結果)という形のタプルの集合変数gを用意 します. \begin{verbatim} > g = group s in Sales by (s.soldCommodtiyNo) with (partition^amountSold.sum()); \end{verbatim} \begin{itemize} \item \begin{verbatim}group s in Sales\end{verbatim} Salesクラスのオブジェクトsについてgroup化する.sは範囲変数とい います. \item \begin{verbatim}by (s.soldCommodityNo)\end{verbatim} byの後にgroup化を行なう属性名を指定します. オブジェクトsのsoldCommodityNoによってgroup化する. \item \begin{verbatim}with (partition^amountSold.sum())\end{verbatim} withの後には,各groupに対し,どのような集約計算を行なうかを指 定します.group化された後の個々の集合をpartitionとして扱います. partitionに対し,amountSoldの合計を求めます. partitionの要素数を求める場合は, partition.count()とします.\\ \clearpage 各partitionに対し集約計算を行なわず,実際の要素を集合として出す場合は, \begin{verbatim}partition^amountSold\end{verbatim}とします.取り出した結果は下の表のようになります. この場合最初に宣言するタプルの中で集合であることを指定しておく必要があ ります \begin{verbatim} Bag<[Integer CommodityNo,Bag TotalSales]> g; \end{verbatim} \begin{center} \epsfile{file=group2.eps} \end{center} \end{itemize} \section{order-by} order-by句を使うとデータベースからデータを取り出すときに,順序を並べ替えて取 り出すことができます.order-by句で指定した属性に従って,その属性値の順 で,昇順または降順で並べ替えることができます.SQLでは, \begin{verbatim} select 取り出したい属性名 from テーブル order by ソートを行なう属性名 \end{verbatim} という記述ができます. Jasmineで並べ替えを行なうには,sort()関数を使用します.sort()は,単一 型の集合,複合型の集合に使えます.昇順(ASCEND),降順(DESCEND)を指定する ことができ,指定しなかった場合は昇順になります. \begin{itemize} \item 単一型の集合の場合\\ \begin{verbatim} > Bag i; > i={4,7,6,3}; > i.sort().print(); Bag{ 3, 4, 6, 7 } > i.sort(DESCEND).print(); Bag{ 7, 6, 4, 3 } \end{verbatim} \item 複合型の集合の場合\\ この場合,sort()の引数として,ソートを行なう属性名を指定する必要があり ます. \begin{verbatim} >Bag s; >s = Sales from Sales; >s.sort(``amountSold'').print(); >s.sort(``amountSold'',DESCEND).print(); \end{verbatim} \end{itemize} 注:上の例のようにある集合Aに対し,A.sort()としても,元の集合Aは実際に は並べ替えられません.A.sort().print()というのは,集合Aをソートした順に 表示するという意味です.並べ替えを元の集合に反映させるには, A=A.sort()とし,元の集合に代入してやる必要があります. \clearpage \section{問い合わせ例} これまで,見てきた問い合わせ (selection,projection,join,group-by,order-by)を組み合わせることにより より複雑な集約計算を行なうことができます.以下では次のようなクエリにつ いて考えてみます. ``得意先ごとの売り上げを売り上げが多い順に,その得意先名と売り上げを出力す る'' \begin{center} \epsfile{file=query.eps} \end{center} \begin{enumerate} \item Join , projection\\ 得意先クラス,売上クラスを得意先番号によってJoinを行ない,新しくできた 表から得意先名,売上額をprojectionによって取り出します.(表1) \begin{verbatim} > Bag<[String customer,Integer sales]> result; > result = [Customer.customerName,Sales.amountSold] from Customer, Sales where Customer.customerNo == Sales.purchaserNo \end{verbatim} \item group-by\\ 1の結果の表に対し,得意先名によってグループ化し,各グループごとの売り 上げの合計(sum)を求めます.(表2) \begin{verbatim} > result = group g in result by (g.customer) with (partition^sales.sum()); \end{verbatim} \item order-by\\ 2の結果を売上総額の多い順(降順)に並べ替えます.(表3) \begin{verbatim} > result = result.sort(``sales'',DESCEND); \end{verbatim} 注:問い合わせの結果を求める手順は1つとは限りません.例えば,上では1つの例 を示しましたが,最初にgroup-byをした後にJoinを行なうこともできます. \end{enumerate} \section{実習} group-by,order-by,さらにselection,projection,joinを組み合わせて問い合 わせを行ないましょう.Commodityクラス,Customerクラス,Salesクラスにサ ンプルデータを挿入するファイルを\\/u/ryu/work/rinkou/database/querydata.odqlに置いとき ます.自分でデータを作って挿入しても構いません.以下のような問い合わせ をやってみてください. \begin{itemize} \item 問い合わせ例 \begin{enumerate} \item 得意先ごとに何を売ったか\\ 結果例 \begin{verbatim} Bag{ [store: "Astore", fruits: Bag{ "Orange", "Grape", "Mellon" }], [store: "Bstore", fruits: Bag{ "Orange", "Banana", "Apple" }], [store: "Csotre", fruits: Bag{ "Grape", "Mellon", "Apple", "Orange" }] } \end{verbatim} \item 得意先ごとに売り上げの平均値を求め,多い順に出力\\ 結果例 \begin{verbatim} Bag{ [store: "Astore", salesAverage: 1066], [store: "Csotre", salesAverage: 600], [store: "Bstore", salesAverage: 466] } \end{verbatim} \end{enumerate} \end{itemize} \end{document}