PostgreSQL で集計関数を使うとき、COUNT と SUM では挙動が異なる点に注意が必要です。特に「該当レコードがない場合」の挙動はよく混乱します。
COUNT の挙動
COUNT(*) / COUNT(column) は 必ず 0 以上 の値を返す
COUNT(column) は NULL 値を無視してカウントする
該当レコードがない場合は 0 を返す
SUM の挙動
SUM(column) は該当レコードが 1件もない場合は NULL を返す
NULL 値は無視されるが、集計対象が 0 件なら結果は NULL
SUM を 0 にしたい場合
COALESCE を使うと NULL を 0 に変換できます。
補足
集計関数 該当レコードなしの場合
COUNT(*) / COUNT(column) 0
SUM(column) / AVG(column) / MAX(column) / MIN(column) NULL
COUNT は行数をそのままカウントするため常に 0 以上
SUM などは対象が存在しないと NULL になるため、必要に応じて COALESCE で値を補正