集計ファンクションにおけるNULLの扱いとDISTINCTを使用した集計処理

Oracle Master Silver

Oracleデータベースの集計ファンクション(SUM、AVG、MAX、MIN、COUNTなど)は、データ分析やレポート作成に欠かせない重要な機能です。本記事では、初心者の方にもわかりやすいように以下の2点について解説します。

  1. 集計ファンクションにおけるNULLの扱い
  2. DISTINCTを使用した集計処理

この記事では、特定の学習用に作成した**EMP_TESTテーブル**を使用します。このテーブルには従業員情報が格納されており、以下にCREATE文とINSERT文を記載します。


使用するテーブル

以下のSQLを実行して、EMP_TESTテーブルを作成しデータを挿入してください。

-- テーブル作成
CREATE TABLE EMP_TEST (
EMP_ID NUMBER PRIMARY KEY, -- 従業員ID
NAME VARCHAR2(50), -- 名前
JOB VARCHAR2(50), -- 職種
SAL NUMBER, -- 給与
DEPT_ID NUMBER, -- 部署ID
BONUS NUMBER -- ボーナス
);

-- データ挿入
INSERT INTO EMP_TEST VALUES (1, 'Alice', 'Manager', 3000, 10, NULL);
INSERT INTO EMP_TEST VALUES (2, 'Bob', 'Clerk', NULL, 20, NULL);
INSERT INTO EMP_TEST VALUES (3, 'Charlie', 'Analyst', 4000, 10, 500);
INSERT INTO EMP_TEST VALUES (4, 'David', 'Clerk', 2500, 30, 300);
INSERT INTO EMP_TEST VALUES (5, 'Emma', 'Salesman', 2000, 30, 200);
INSERT INTO EMP_TEST VALUES (6, 'Frank', 'Manager', 3000, 20, NULL);
INSERT INTO EMP_TEST VALUES (7, 'Grace', 'Analyst', 4000, 20, 500);
INSERT INTO EMP_TEST VALUES (8, 'Helen', 'Salesman', 2000, 30, 200);
INSERT INTO EMP_TEST VALUES (9, 'Ian', 'Clerk', 2500, 20, NULL);
INSERT INTO EMP_TEST VALUES (10, 'Jane', 'Clerk', NULL, 10, NULL);
COMMIT;

1. 集計ファンクションにおけるNULLの扱い

集計ファンクションのNULLの基本ルール

Oracleの集計ファンクションでは、基本的にNULL値を無視して計算します。ただし、COUNT(*)は例外で、NULL値を含むすべての行をカウントします。

以下の表に主要な集計ファンクションとNULLの扱いをまとめました:

ファンクションNULLの扱い
SUM, AVG無視
MAX, MIN無視
COUNT(列名)無視
COUNT(*)カウントする

実例:EMP_TESTテーブルを使用

-- SAL列(従業員の給与)の合計を計算
SELECT SUM(SAL) AS TOTAL_SAL FROM EMP_TEST;

-- 結果
TOTAL_SAL
---------
23000

-- COUNT関数のNULLの扱い
SELECT COUNT(SAL) AS COUNT_SAL, COUNT(*) AS COUNT_ALL FROM EMP_TEST;

-- 結果
COUNT_SAL | COUNT_ALL
----------+----------
8 | 10

解説:

  • SUM(SAL)は、SAL列のNULLを無視して合計を計算します。
  • COUNT(SAL)は、SAL列の値がNULLでない行をカウントします。
  • COUNT(*)は、NULLを含むすべての行をカウントします。

2. DISTINCTを使用した集計処理

DISTINCTの概要

DISTINCTキーワードを使用すると、指定列の重複する値を除外して計算を行います。これにより、重複値を考慮せずに正確な集計が可能になります。


実例:SAL列の合計でDISTINCTを使用

-- SAL列の合計を通常通り計算
SELECT SUM(SAL) AS TOTAL_SAL FROM EMP_TEST;

-- 結果
TOTAL_SAL
---------
23000

-- SAL列にDISTINCTを使用して合計を計算
SELECT SUM(DISTINCT SAL) AS TOTAL_DISTINCT_SAL FROM EMP_TEST;

-- 結果
TOTAL_DISTINCT_SAL
-------------------
15500

解説:

  • SUM(SAL)では、重複する給与額もすべて合計に含まれます。
  • SUM(DISTINCT SAL)では、重複する給与額を除外した結果が表示されます。

COUNT関数とDISTINCT

DISTINCTはCOUNT関数と組み合わせることで、一意の値の数をカウントできます。

-- DEPT_ID列の一意の値の数をカウント
SELECT COUNT(DISTINCT DEPT_ID) AS UNIQUE_DEPT_COUNT FROM EMP_TEST;

-- 結果
UNIQUE_DEPT_COUNT
-----------------
3

COUNT(DISTINCT DEPT_ID)では、DEPT_ID列の値の中から重複を除外してカウントしています。


3. 視覚的に理解する:NULLとDISTINCTの違い

以下は、SAL列の元データをもとに、NULLやDISTINCTの扱いを視覚化した例です。

SAL列の元データ

3000, NULL, 4000, 2500, 2000, 3000, 4000, 2000, 2500, NULL

NULLを無視した場合(SUM, AVGなど)

SAL列からNULLを無視
--> すべての値を合計: 23000

DISTINCTを適用した場合

重複値を除外
元データ: 3000, NULL, 4000, 2500, 2000, 3000, 4000, 2000, 2500, NULL
DISTINCT適用後: 3000, 4000, 2500, 2000
--> 合計: 15500

4. 注意点とベストプラクティス

  1. NULL値の影響を理解する: 集計ファンクションはNULLを無視するため、NULLを含む列の集計を行う際には、結果が意図通りであるかを確認しましょう。
  2. DISTINCTを使う際のパフォーマンス: DISTINCTは重複排除の処理が加わるため、大量データに適用するとパフォーマンスに影響が出る場合があります。
  3. COUNT(*)とCOUNT(列名)の違い: COUNT(*)はNULLを含むすべての行をカウントしますが、COUNT(列名)はNULLを無視します。意図した動作を確認して使用しましょう。

まとめ

  • 集計ファンクション(SUM、AVG、MAX、MIN、COUNT)は、基本的にNULLを無視して計算します。ただし、COUNT(*)はNULLを含むすべての行をカウントします。
  • DISTINCTを使用すると、指定列の重複を除外して集計が可能です。
  • NULL値やDISTINCTの扱いを正確に理解することで、より効率的なデータ分析が可能になります。

この記事で紹介したEMP_TESTテーブルを使いながら、SQLを実際に実行して理解を深めてください!

[参考]
Oracle Database SQL言語リファレンス 19c

コメント

タイトルとURLをコピーしました