コマンド道場

$ man sum

SUM

集約関数

合計を求める。対象が 1 行も無いときは 0 ではなく NULL を返す。

呼び出しの形

SUM(式)
SUM(DISTINCT 式)

つまずきやすいところ

  • 対象が 0 行のときは NULL です。0 を期待して足し算を続けると、そこから先がすべて NULL になります。

  • SUM は NULL を無視するので、NULL を 0 と同じに扱っているわけではありません。平均(AVG)では割る数が変わるため、この違いが結果に出ます。

  • 浮動小数点(double precision)の合計は、足す順番で最後の桁が変わることがあります。金額は numeric を使ってください。

実行例

結果は実際に流したものです。同じ SQL を 自由に打てる画面 で試すと、同じ結果になります。

明細の合計金額を求める
SELECT SUM(suryo * tanka) AS uriage FROM juchu_meisai
uriage
398740

1

1 行も該当しないときは NULL になる
SELECT SUM(suryo) AS goukei FROM juchu_meisai WHERE juchu_id = 9999
goukei
NULL

1

0 ではありません。ここが SUM のいちばんの落とし穴です。

COALESCE で 0 にそろえる
SELECT COALESCE(SUM(suryo), 0) AS goukei FROM juchu_meisai WHERE juchu_id = 9999
goukei
0

1

「該当なし」を 0 として扱いたいときの定石です。

説明

SUM は数値の合計を返します。NULL は無視して足します。したがって「NULL があると合計まで NULL になる」ことはありません。

⚠️ ただし、足す相手が 1 行も無いときだけは別です。このとき SUM0 ではなく NULL を返します。「該当なし」と「合計が 0」を区別するための仕様ですが、0 のつもりで受け取ると計算がそこから NULL に汚染されます。

金額のように必ず数値がほしい場面では、COALESCE(SUM(...), 0) と包むのが定石です。

型にも注意が必要です。integer どうしを足すと結果は bigintnumeric を足すと numeric になります。金額は numeric で持つのが安全です。

次に読む

関係する関数

根拠にした一次情報