0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Oracle Database SQL (1Z0-071-JPN)試験 集計ファンクション【第6章_前編】

0
Last updated at Posted at 2026-04-05

集計ファンクションとは

複数件のデータを集計するためのファンクション(グループ関数とも呼ばれる)。グループ化されたデータに対して、グループごとに1行の結果を返す。

主要な特徴:

  • SELECT句、HAVING句、ORDER BY句でのみ使用可能
  • WHERE句には集計ファンクションを使えない(集計はグループ化後に行われるため)
  • 集計ファンクションの結果を絞り込む場合は、HAVING句を使用する

⚠️ 試験ポイント:集計した結果に条件を付けたい場合は WHERE ではなく HAVING を使う。WHERE は行単位のフィルタリング(グループ化の前)、HAVING はグループ単位のフィルタリング(グループ化の後)。


集計ファンクション一覧

① SUM()

複数行の列値の合計を求める(数値型のみ対象)。

SELECT SUM(sal) FROM emp;
  • GROUP BYなしの場合、全行が1グループとして合計される
  • GROUP BYと組み合わせると、グループ単位での合計が出る

⚠️ 試験ポイント(ORA-00937エラー):
GROUP BYなしで、SUM()などの集計ファンクションと、集計対象外の個別列を同時にSELECTしようとするとエラー(ORA-00937: not a single-group group function)になる。
集計結果と個別列を一緒に取得するにはGROUP BYでその列を指定する必要がある。

-- ❌ エラー
SELECT deptno, SUM(sal) FROM emp;

-- ✅ 正しい
SELECT deptno, SUM(sal) FROM emp GROUP BY deptno;
動作確認

■テストデータ

DROP TABLE dept PURGE;
DROP TABLE emp PURGE;


-- 部門テーブル
CREATE TABLE dept (
    deptno   NUMBER(2)    PRIMARY KEY,
    dname    VARCHAR2(14),
    loc      VARCHAR2(13)
);

-- 社員テーブル
CREATE TABLE emp (
    empno    NUMBER(4)    PRIMARY KEY,
    ename    VARCHAR2(10),
    job      VARCHAR2(9),
    mgr      NUMBER(4),
    hiredate DATE,
    sal      NUMBER(7,2),
    comm     NUMBER(7,2),
    deptno   NUMBER(2)    REFERENCES dept(deptno)
);

INSERT INTO dept (deptno, dname, loc) VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO dept (deptno, dname, loc) VALUES (20, 'RESEARCH',   'DALLAS');
INSERT INTO dept (deptno, dname, loc) VALUES (30, 'SALES',      'CHICAGO');
INSERT INTO dept (deptno, dname, loc) VALUES (40, 'OPERATIONS', 'BOSTON');

-- deptno = 10 (ACCOUNTING)
INSERT INTO emp VALUES (1001, 'SMITH',  'CLERK',     1100, DATE '2020-01-15', 1200,   NULL, 10);
INSERT INTO emp VALUES (1002, 'ALLEN',  'SALESMAN',  1100, DATE '2019-03-10', 1600,   300,  10);
INSERT INTO emp VALUES (1003, 'WARD',   'SALESMAN',  1100, DATE '2018-07-20', 1250,   500,  10);

-- deptno = 20 (RESEARCH)
INSERT INTO emp VALUES (2001, 'JONES',  'MANAGER',   1100, DATE '2017-04-02', 2975,   NULL, 20);
INSERT INTO emp VALUES (2002, 'SCOTT',  'ANALYST',   2001, DATE '2021-12-09', 3000,   NULL, 20);
INSERT INTO emp VALUES (2003, 'ADAMS',  'CLERK',     2002, DATE '2022-01-12', 1100,   NULL, 20);
INSERT INTO emp VALUES (2004, 'FORD',   'ANALYST',   2001, DATE '2019-06-25', 3000,   NULL, 20);

-- deptno = 30 (SALES)
INSERT INTO emp VALUES (3001, 'MARTIN','SALESMAN',   1100, DATE '2020-09-28', 1250,  1400, 30);
INSERT INTO emp VALUES (3002, 'BLAKE', 'MANAGER',    1100, DATE '2015-05-01', 2850,   NULL, 30);
INSERT INTO emp VALUES (3003, 'TURNER','SALESMAN',   3002, DATE '2019-09-08', 1500,     0, 30);
INSERT INTO emp VALUES (3004, 'JAMES', 'CLERK',      3002, DATE '2021-12-03',  950,   NULL, 30);

-- deptno = 40 (OPERATIONS)
INSERT INTO emp VALUES (4001, 'MILLER','CLERK',      2001, DATE '2020-01-23', 1300,   NULL, 40);
INSERT INTO emp VALUES (4002, 'CLARK', 'MANAGER',    1100, DATE '2016-06-09', 2450,   NULL, 40);
COMMIT;

■実行結果
エラー
image.png

image.png


② AVG()

複数行の列値の平均を求める(数値型のみ対象)。

SELECT AVG(sal) FROM emp;

⚠️ 試験ポイント:
AVG()はNULLを無視して計算される。つまり、NULLの行は分子(合計)にも分母(行数)にも含まれない。
NVL()でNULLを0に変換してからAVGを使うと、分母にNULL行が含まれ、結果が変わることがある点に注意。

動作確認

■実行結果
image.png


③ MAX()

複数行の列値の最大値を求める。

SELECT MAX(sal) FROM emp;
SELECT MAX(ename) FROM emp;  -- 文字列も可
SELECT MAX(hiredate) FROM emp;  -- 日付も可
  • 数値型以外(文字列・日付型)にも使用可能
  • NULLは無視される
動作確認

■実行結果
image.png

文字列
image.png

日時
image.png


④ MIN()

複数行の列値の最小値を求める。

SELECT MIN(sal) FROM emp;
  • 数値型以外(文字列・日付型)にも使用可能
  • NULLは無視される
動作確認

■実行結果
image.png


⑤ COUNT()

⚠️ 番号ミスの修正:元の記事では「④COUNT」と記載されていたが、正しくは⑤番目。

行数を数えるファンクション。COUNT(*)とCOUNT(列名)で動作が異なる点が最重要ポイント。

書き方 NULLの扱い 説明
COUNT(*) NULLを含む テーブルの全行数をカウント
COUNT(列名) NULLを除外 指定列にNULL以外の値がある行数のみカウント
COUNT(DISTINCT 列名) NULLを除外 重複・NULLを除いたユニーク値の件数
SELECT COUNT(*) FROM emp;              -- 全行数(NULL含む)
SELECT COUNT(comm) FROM emp;           -- commがNULLでない行数
SELECT COUNT(DISTINCT deptno) FROM emp; -- 重複なし件数
動作確認

■実行結果
image.png

image.png

***

NULLの扱い

集計ファンクションにおけるNULLの基本ルール:

関数 NULLの扱い
SUM / AVG 無視(計算対象外)
MAX / MIN 無視(NULL以外から最大・最小を探す)
COUNT(列名) 無視(NULLの行はカウントしない)
COUNT(*) 含む(NULLのある行も1行としてカウント)

⚠️ AVGのNULL注意点:
NVL()等を使って事前にNULLを0に変換すると、分母(行数)が増えるため、平均値が変わる。どちらの挙動が求められているかを問題文で確認すること。


DISTINCTの使用

DISTINCTを集計ファンクション内に指定すると、重複データを除いてから集計が実行される。

SELECT COUNT(DISTINCT deptno) FROM emp;
SELECT SUM(DISTINCT sal) FROM emp;
SELECT AVG(DISTINCT sal) FROM emp;
動作確認

■テストデータ

INSERT INTO emp (empno, ename, job, mgr, hiredate, sal,    comm, deptno) VALUES
(9001, 'A_SMITH',  'CLERK',    NULL, DATE '2024-01-01', 1000,  NULL, 10);
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal,    comm, deptno) VALUES
(9002, 'B_ALLEN',  'CLERK',    NULL, DATE '2024-01-02', 1000,  NULL, 10);
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal,    comm, deptno) VALUES
(9003, 'C_WARD',   'CLERK',    NULL, DATE '2024-01-03', 2000,  NULL, 20);
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal,    comm, deptno) VALUES
(9004, 'D_JONES',  'CLERK',    NULL, DATE '2024-01-04', 3000,  NULL, 30);
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal,    comm, deptno) VALUES
(9005, 'E_BLAKE',  'CLERK',    NULL, DATE '2024-01-05', 3000,  NULL, 30);
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal,    comm, deptno) VALUES
(9006, 'F_CLARK',  'CLERK',    NULL, DATE '2024-01-06', NULL,  NULL, 30);

COMMIT;

image.png

image.png

image.png

使用できる・できない構文:

構文 可否 理由
COUNT(DISTINCT 列名) ✅ 使用可 NULLを除いた重複なし件数
COUNT(DISTINCT *) ❌ 使用不可 *にDISTINCTは指定できない(構文エラー)
SUM(DISTINCT 列名) ✅ 使用可 重複を除いた合計
AVG(DISTINCT 列名) ✅ 使用可 重複を除いた平均

⚠️ COUNT(DISTINCT *) はエラーになる。DISTINCTと組み合わせる場合は必ず列名を指定する。


試験頻出ポイントまとめ

ポイント 内容
WHERE句 集計ファンクションは使えない → HAVING句を使う
COUNT(*)とCOUNT(列名) COUNT(*)はNULL含む、COUNT(列名)はNULL除外
AVGのNULL NULLは分子・分母ともに除外される(NVL変換で挙動が変わる)
MAX/MINの対象型 数値・文字列・日付すべてに対応
COUNT(DISTINCT *) 構文エラー(列名を指定する必要あり)
GROUP BYなしの複数列SELECT 集計ファンクションと個別列の混在はエラー(ORA-00937)

参考

Oracle SQL 集計関数のNULL対策とDISTINCTの使い方
https://oracle-master00000.com/null-distinct001/

Oracle Database SQL (1Z0-071-JPN)試験 NULLとDISTINCTの扱い(Qiita)
https://qiita.com/n-aaaa/items/3b4d3d66aeca9a6f19e9

SQLのHAVING句の使い方(各DB共通/Oracle含む解説)
https://cs-techblog.com/db/sql-having-of/

【SQL】HAVING句の使い方を1分でわかりやすく解説
https://it-biz.online/it-skills/having/

SQLのHAVING句とは?(OracleやMySQLで使用する方法)
https://it-kyujin.jp/article/detail/1755/

【SQL】DISTINCTとは?重複行をまとめる基本の使い方から簡単なサンプルまで
https://blastengine.jp/blog_content/sql-distinct/

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?