今回はPostgreSQLのSUMを使い、商品の価格を合計します。取得したデータの意味を整理します。
所要時間は15分ほどです。
それでは、さっそく始めていきましょう!
用語と今回の対象
SUMは、対象の行にある数値を合計する集約関数です。COUNTは件数を数える関数です。
取得元はpublic.productsで、1行が1商品を表します。
| 列名 | 意味 |
|---|---|
| product_id | 商品ID |
| product_name | 商品名 |
| price_yen | 価格(円) |
今回求めるのは、テーブルに登録された価格の合計です。販売数量を使わないため、売上額ではありません。
| 記述 | 求めるもの |
|---|---|
| COUNT(*) | 対象の行数 |
| SUM(price_yen) | 対象の行にある価格の合計 |
演習①:現在のデータと合計を確認する
まず商品データを確認しました。
SELECT product_id, product_name, price_yen
FROM public.products
ORDER BY product_id;
| product_id | product_name | price_yen |
|---|---|---|
| 1 | onigiri | 100 |
| 2 | bento | 500 |
| 3 | ame | 50 |
| 4 | pan | 100 |
続けて件数と合計を取得しました。
SELECT
COUNT(*) AS product_count,
SUM(price_yen) AS total_price_yen
FROM public.products;
| product_count | total_price_yen |
|---|---|
| 4 | 750 |
4商品の価格100円、500円、50円、100円を足した結果は750円でした。
ここで、0円の商品が1行追加された場合を考えました。回答は「商品数は5になり、価格の合計は変わらない」でした。
0円でも行は増えるためCOUNT(*)は増えます。一方、価格の合計に0円を足しても750円のままです。これは仮定への回答で、実際に商品を追加したわけではありません。
演習②:100円以上の商品に絞る
次に、価格が100円以上の商品数と価格の合計を、自分でSQLを書いて取得しました。
実際に実行したSQLは次のとおりです。
SELECT
COUNT(product_id) AS product_count,
SUM(price_yen) AS total_price_yen
FROM public.products
WHERE price_yen >= 100;
| product_count | total_price_yen |
|---|---|
| 3 | 700 |
100円、500円、100円の3商品が対象となり、合計は700円でした。
「ちょうど100円の商品も含まれるか」という確認には、「含まれます」と回答しました。>= 100は100以上を意味するため、100円ちょうども対象です。
COUNT(*)とCOUNT(product_id)の違い
課題ではCOUNT(*)が指定されていましたが、実行したSQLではCOUNT(product_id)を使いました。
| 記述 | 数える対象 |
|---|---|
| COUNT(*) | 条件に合うすべての行 |
| COUNT(product_id) | 条件に合う行のうち、product_idがNULLではない行 |
今回の対象の商品IDはすべてNULLではないため、結果は同じ3件でした。しかし、常に同じ結果になるとは限りません。商品数を行数として数えるならCOUNT(*)を使います。
結果が合っている場合でも、何を数える式になっているか確認することが復習点でした。
演習③:条件に合う商品がない場合
最後に、1000円以上の商品を対象にしました。
SELECT
COUNT(*) AS product_count,
SUM(price_yen) AS total_price_yen
FROM public.products
WHERE price_yen >= 1000;
| product_count | total_price_yen |
|---|---|
| 0 | NULL(画面では空欄) |
現在のデータには1000円以上の商品がありません。対象の行が0行なのでCOUNT(*)は0になります。一方、SUM(price_yen)はNULLになります。
「SUMの結果は0かNULLか」という確認には、「NULL」と回答しました。画面の空欄は空文字列ではなくNULLの表示です。
対象0行と合計0を区別する
SUMはNULLの値を合計に含めません。対象の行がない場合、または対象の値がすべてNULLの場合、結果はNULLです。
0円の価格がある場合と、合計する値がない場合は異なります。例えば0円の商品だけが対象なら合計は0ですが、今回の1000円以上の条件では対象の行自体がありません。
なお、画像の末尾には「1行」と表示されました。これは集計結果が1行返ったことを意味し、条件に合う商品が1つあったという意味ではありません。商品の対象件数はproduct_countの0で確認できます。
学習記録
| 確認項目 | 確認できた内容 |
|---|---|
| 全体の価格を合計する | 4商品・750円を確認 |
| 0円と件数の関係を説明する | 0円の商品追加で件数だけ増えると回答 |
| WHEREで対象を絞る | 100円以上で3商品・700円を確認 |
| 境界の値を判定する | 100円ちょうども含むと回答 |
| 対象がない場合を理解する | COUNTは0、SUMはNULLを確認 |
条件付きの演習ではCOUNT()の代わりにCOUNT(product_id)を使いました。その違いを説明した後、最後の演習ではCOUNT()を使って実行しました。
まとめ
SUMは数値を合計し、COUNTは件数を数えます。WHEREを使えば合計する対象を限定できます。
対象の行がない場合、COUNTは0、SUMはNULLになります。対象件数と合計値を並べて確認すると、結果の意味を読み取りやすくなります。今回のSELECTで保存済みのデータは変更していません。