$ 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 行
SELECT SUM(suryo) AS goukei FROM juchu_meisai WHERE juchu_id = 9999
| goukei |
|---|
| NULL |
1 行
0 ではありません。ここが SUM のいちばんの落とし穴です。
SELECT COALESCE(SUM(suryo), 0) AS goukei FROM juchu_meisai WHERE juchu_id = 9999
| goukei |
|---|
| 0 |
1 行
「該当なし」を 0 として扱いたいときの定石です。
説明
SUM は数値の合計を返します。NULL は無視して足します。したがって「NULL があると合計まで NULL になる」ことはありません。
⚠️ ただし、足す相手が 1 行も無いときだけは別です。このとき SUM は 0 ではなく NULL を返します。「該当なし」と「合計が 0」を区別するための仕様ですが、0 のつもりで受け取ると計算がそこから NULL に汚染されます。
金額のように必ず数値がほしい場面では、COALESCE(SUM(...), 0) と包むのが定石です。
型にも注意が必要です。integer どうしを足すと結果は bigint、numeric を足すと numeric になります。金額は numeric で持つのが安全です。
次に読む
根拠にした一次情報
- PostgreSQL 18 マニュアル: 集約関数(2026-09-02 確認)