SQL 小計を利用する

何かの統計システムなどを作っていると、よく複数項目で小計をとる場面にであう。これを実現するためにGROUP BY句を使用すると、小計単位でSQLを発行しなければならない。また、小計でソートを行いたいときにアプリケーション側で制御するのも面倒だ。OVER関数を利用すれば、これらをひとつのSQLで実現できる。

環境

  • Oracle10g R2

サンプル

例えば以下のようなテーブル「T_SHAIN」があるとする。

JIGYOUSHO_CD BUSHO_CD SHAIN_CD
1 101 50001
1 101 50002
1 102 50003
1 102 50004
1 101 50005
1 101 50006
1 101 50007
1 102 50008
1 102 50009
2 201 50010
3 301 50011
1 101 50012
2 202 50013
2 202 50014
2 202 50015
2 202 50016
2 201 50017
1 101 50018
2 202 50019
1 102 50020

このテーブルを使って「事業所単位」「部署単位」で社員数を集計し、結果を社員数の多い事業所順&社員数の少ない部署順で取得したい。

GROUP BY句を使用する場合
 SELECT
   JIGYOUSHO_CD,
   COUNT(SHAIN_CD) AS TOTAL_JIGYOUSHO
 FROM
   T_SHAIN
 GROUP BY
   JIGYOUSHO_CD
 ORDER BY
   TOTAL_JIGYOUSHO DESC
JIGYOUSHO_CD TOTAL_JIGYOUSHO
1 12
2 7
3 1
 SELECT
   JIGYOUSHO_CD,
   BUSHO_CD,
   COUNT(SHAIN_CD) AS TOTAL_BUSHO
 FROM
   T_SHAIN
 GROUP BY
   JIGYOUSHO_CD,
   BUSHO_CD
 ORDER BY
   TOTAL_BUSHO
JIGYOUSHO_CD BUSHO_CD TOTAL_BUSHO
3 301 1
2 201 2
2 202 5
1 102 5
1 101 7

そしてこれらの取得結果をfor文でまわしながら、事業所コードで合致させ、さらに事業所全体の社員数が多く、かつ部署の社員数が少ない順にソート…となるとコーディングもややこしくなる。

OVER関数を使用する場合
 SELECT DISTINCT
   JIGYOUSHO_CD,
   BUSHO_CD,
   COUNT(SHAIN_CD) OVER (PARTITION BY JIGYOUSHO_CD) AS TOTAL_JIGYOUSHO,
   COUNT(SHAIN_CD) OVER (PARTITION BY JIGYOUSHO_CD,BUSHO_CD) AS TOTAL_BUSHO
 FROM
   T_SHAIN
 ORDER BY
   TOTAL_JIGYOUSHO DESC,
   TOTAL_BUSHO
JIGYOUSHO_CD BUSHO_CD TOTAL_JIGYOUSHO TOTAL_BUSHO
1 102 12 5
1 101 12 7
2 201 7 2
2 202 7 5
3 301 1 1

OVER関数を使用すると、PARTITION BY句でGROUP BY句と同じように集計関数に対する集合範囲を定義することができる。これはSQL文で複数指定することが可能であるため、事業所単位と部署単位を同時に取得できる。
さらに取得フィールド名として定義すれば、ORDER BY句に指定することができるので、小計単位でソート順を自由に組み合わせられる。

説明


サンプルではCOUNT関数で社員数を求めたが、SUM関数などの集計関数ならば同様に利用することができる。これにより、例えば「営業社員数が少ないのに売上額が高い支社」「生産数が少ないのに不良品数が多い工場」などを簡易に計上できる。