Oracle SQL 関数 : SUM : データの合計値を返す

 numberRet := SUM( [ALL , DISTINCT] <expr> [ OVER <分析句> ] )

SUMは集計関数、または分析関数として使用します。
<expr>がNULLの項目は計算されません。また、DISTINCT指定の場合は重複行は計算されません。

簡単な例として、単なる合計を求めるSQL文と、GROUP BY句を使用したSQL文を以下に示します。
最初の例は、売上明細の全ての売上金額を合計しています。条件付けのWHERE句がありませんのでTT_売上明細に存在する全ての行が対象になります。

2番目の例は、売上番号毎の売上金額の合計を計算しています。共にSUM関数の中で数量と単価の乗算を行っていますが、括弧の中は<式>が許されますので、<式>として問題の無いものはすべて許されます。

SQL> SELECT SUM(売上数量 * 売上単価) AS 売上金額
  2  FROM TT_売上明細;

  売上金額
----------
   3736000

SQL> SELECT 売上番号, SUM(売上数量 * 売上単価) AS 売上金額
  2  FROM TT_売上明細
  3  GROUP BY 売上番号
  4  ORDER BY 売上番号;

  売上番号   売上金額
---------- ----------
         1     188000
         2     560000
         3     570000
         4     396000
         5     696000
         6     454000
         8     618000
         9     254000

8行が選択されました。

次に2個のテーブルを利用して別の項目でグループ化を行ってSUM関数を利用する例を示します。
最初のSQL文は、TT_売上TT_売上明細から得意先毎の売上金額の合計を求めます。
WHERE句で売上伝票のヘッダーデータであるTT_売上の売上番号とTT_売上明細の売上番号でリンクを張り、TT_売上の得意先コードでグループ化を行います。(売上先を示す得意先コードはヘッダーにしか持たない為、当然この様になります)
2番目のSQL文は最初とは視点を変えて、担当者ごとの売上金額の合計を求めます。

SQL> SELECT TH.得意先コード, SUM(TD.売上数量 * TD.売上単価) AS 売上金額
  2  FROM TT_売上 TH, TT_売上明細 TD
  3  WHERE TH.売上番号 = TD.売上番号
  4  GROUP BY TH.得意先コード
  5  ORDER BY TH.得意先コード;

得意先コード   売上金額
------------ ----------
           1    1514000
           2     560000
           3     396000
           4     570000
           5     696000

SQL> SELECT TH.担当者コード, SUM(TD.売上数量 * TD.売上単価) AS 売上金額
  2  FROM TT_売上 TH, TT_売上明細 TD
  3  WHERE TH.売上番号 = TD.売上番号
  4  GROUP BY TH.担当者コード
  5  ORDER BY TH.担当者コード;

担当者コード   売上金額
------------ ----------
           1    1060000
           2     396000
           4     560000
           5     570000
           7     696000
           9     454000

6行が選択されました。

集計(グループ)の基準となるコードに対応するデータが存在しない場合も表示する方法


上の例では 得意先コード , 担当者コード 毎に集計を表示しましたが、該当するそれぞれの売上データが存在しない場合もあります。 この場合にもデータ行として表示させるには外部結合(LEFT JOIN)を使います。
尚、注意が必要なのは SUM 関数が対象とするのはデータが NULL では無いもののみです。

以下のSQLを見て下さい。 WHERE句の中で TM_得意先 が主体となりますので TT_売上 側の方に (+) を付加します。 さらに TT_売上明細 側にも (+) を付加します。
尚、今回の例の為 TM_得意先 に得意先コードが「6」となるデータを新たに追加しました。
SQL> SELECT TM.得意先コード, SUM(TD.売上数量 * TD.売上単価) AS 売上金額
  2  FROM TM_得意先 TM, TT_売上 TH, TT_売上明細 TD
  3  WHERE TM.得意先コード = TH.得意先コード(+)
  4  AND   TH.売上番号 = TD.売上番号(+)
  5  GROUP BY TM.得意先コード
  6  ORDER BY TM.得意先コード;

得意先コード   売上金額
------------ ----------
           1    1514000
           2     560000
           3     396000
           4     570000
           5     696000
           6

6行が選択されました。

SQL> SELECT TM.担当者コード, SUM(TD.売上数量 * TD.売上単価) AS 売上金額
  2  FROM TM_担当者 TM, TT_売上 TH, TT_売上明細 TD
  3  WHERE TM.担当者コード = TH.担当者コード(+)
  4  AND   TH.売上番号 = TD.売上番号(+)
  5  GROUP BY TM.担当者コード
  6  ORDER BY TM.担当者コード;

担当者コード   売上金額
------------ ----------
           1    1060000
           2     396000
           3
           4     560000
           5     570000
           6
           7     696000
           8
           9     454000

9行が選択されました。

NULLが返される可能性がある SUM には NVL を使用する


上の例では売り上げが存在しない 得意先コード , 担当者コード の行が空白(NULL)の表示でしたが、 SUM の結果に NVL を適用して NULL をゼロに変換すれば表示が正しくなります。 (NULLのままで良い場合にはそのままでOKですが)
SQL> SELECT TM.得意先コード, NVL(SUM(TD.売上数量 * TD.売上単価), 0) AS 売上金額
  2  FROM TM_得意先 TM, TT_売上 TH, TT_売上明細 TD
  3  WHERE TM.得意先コード = TH.得意先コード(+)
  4  AND   TH.売上番号 = TD.売上番号(+)
  5  GROUP BY TM.得意先コード
  6  ORDER BY TM.得意先コード;

得意先コード   売上金額
------------ ----------
           1    1514000
           2     560000
           3     396000
           4     570000
           5     696000
           6          0

6行が選択されました。

SQL> SELECT TM.担当者コード, NVL(SUM(TD.売上数量 * TD.売上単価), 0) AS 売上金額
  2  FROM TM_担当者 TM, TT_売上 TH, TT_売上明細 TD
  3  WHERE TM.担当者コード = TH.担当者コード(+)
  4  AND   TH.売上番号 = TD.売上番号(+)
  5  GROUP BY TM.担当者コード
  6  ORDER BY TM.担当者コード;

担当者コード   売上金額
------------ ----------
           1    1060000
           2     396000
           3          0
           4     560000
           5     570000
           6          0
           7     696000
           8          0
           9     454000

9行が選択されました。

得意先コード毎の SUM を求める部分を副問合せとして FROM 句で処理する方法


上記のSQLを得意先コード毎の SUM を求める部分を1つのSQLとして FROM 句の中で記述し、 その結果と TM_得意先 とリンクする方法があります。
この方法は、副問合せの中をいろんなものにして別の条件でデータを絞り込む場合にも使えると思います。
SQL> SELECT TM.得意先コード, NVL(TX.売上金額, 0) AS 売上金額
  2  FROM
  3   TM_得意先 TM,
  4   (  /* 得意先コード毎の売上金額集計 */
  5    SELECT
  6     TU.得意先コード
  7    ,NVL(SUM(TD.売上数量 * TD.売上単価), 0) AS 売上金額
  8    FROM TT_売上 TU , TT_売上明細 TD
  9    WHERE TU.売上番号 = TD.売上番号
 10    GROUP BY TU.得意先コード
 11   ) TX
 12  WHERE TM.得意先コード = TX.得意先コード(+)
 13  ORDER BY TM.得意先コード;

得意先コード   売上金額
------------ ----------
           1    1514000
           2     560000
           3     396000
           4     570000
           5     696000
           6          0

6行が選択されました。
ちなみに担当者コード毎の方は以下の様になります。
SQL> SELECT TM.担当者コード, NVL(TX.売上金額, 0) AS 売上金額
  2  FROM
  3   TM_担当者 TM,
  4   (  /* 担当者コード毎の売上金額集計 */
  5    SELECT
  6     TU.担当者コード
  7    ,NVL(SUM(TD.売上数量 * TD.売上単価), 0) AS 売上金額
  8    FROM TT_売上 TU , TT_売上明細 TD
  9    WHERE TU.売上番号 = TD.売上番号
 10    GROUP BY TU.担当者コード
 11   ) TX
 12  WHERE TM.担当者コード = TX.担当者コード(+)
 13  ORDER BY TM.担当者コード;

担当者コード   売上金額
------------ ----------
           1    1060000
           2     396000
           3          0
           4     560000
           5     570000
           6          0
           7     696000
           8          0
           9     454000

9行が選択されました。