グループ処理とグループ関数
単一行関数は図1のとおり、1つの行の値をもとに1つの値を返します。
一方、グループ関数は図2のとおり、複数の行の値をもとに1つの値を返します。
主なグループ関数は、表1のとおりです。
関数 | 説明 |
---|---|
AVG(列) | 列の平均値 |
COUNT(列) | 列の値がNULL以外の行数 |
MAX(列) | 列の最大値 |
MIN(列) | 列の最小値 |
SUM(列) | 列の合計値 |
図2からわかるようにグループ関数が戻す値は1つなので、SELECT
句において、グループ関数と複数の値を返す列を並べて記述することはできません。つまり、実行例1はエラーになります。
SQL> SELECT last_name,AVG(salary) FROM employees; SELECT last_name,AVG(salary) FROM employees * 行1でエラーが発生しました。: ORA-00937: 単一グループのグループ関数ではありません。
バラして実行してみるとわかりますが、「SELECT last_name FROM employees
」は全従業員(employees)の、それぞれの名前(last_name)が返されます。
SQL> SELECT last_name FROM employees; LAST_NAME --------------- Abel Ande Atkinson Austin Baer (途中省略) Walsh Weiss Whalen Zlotkey 107行が選択されました。
しかし、「SELECT AVG(salary) FROM employees
」は、全従業員(employees)の唯一の平均給与(AVG(salary)
)が返されます。
SQL> SELECT AVG(salary) FROM employees; AVG(SALARY) ----------- 6461.83178
複数行分の値と1行分の値を同時に表示してくれとお願いしても、「無理!(単一グループのグループ関数ではありません)」と言われて当然です。
問1
次のSQL文を確認してください。
SELECT promo_name,MAX(promo_cost) FROM promotions WHERE PROMO_BEGIN_DATE BETWEEN TO_DATE('20000101','YYYYMMDD') AND TO_DATE('20001231','YYYYMMDD');
2000年の上半期に開始されたプロモーションの中で、最もコストをかけているプロモーションの名前と金額を求める必要があります。この問合せを実行するとどのような結果になりますか。
- a. 正常に実行される
- b. グループ関数が使用されているSQL文において条件付けする場合は、HAVING句を使用しなければいけないためエラーになる
- c. 集約関数を使用する場合は、GROUP BY句が必要なためためエラーになる
- d. SELECT句にグループ処理されないpromo_nameが記述されているためエラーになる
前述の実行例1を理解していれば、正解は選択肢dであることはすぐにわかったことでしょう。
グループ関数は、複数の行を1つのグループとして処理することができる関数ですが、GROUP BY
句が必ず必要というわけではありません(選択肢cは不正解)。問題1のように、GROUP BY
句が使用されていなくても、WHERE
句の条件を満たすすべての行を1つのグループとして処理できます。
また、グループ関数の結果に対する条件付けはHAVING
句で行わなければいけませんが、通常の列に対して行う、処理対象を絞り込むための条件はWHERE
句で記述できます(選択肢bは不正解)。
グループ処理単位(GROUP BY
句に記述)にグループ関数の結果を表示することはできますが、グループ処理単位ではない列(GROUP BY
句に記述していない列)と、グループ関数の結果を同一行で表示することはできません。つまり、GROUP BY
句に記載した列はSELECT
句に記述できますが、GROUP BY
句に記載していない列はSELECT
句に記述できません(エラーになります)。グループ関数を使用するときには、この点に注意する必要があります。
【重要】グループ関数を使用するときの注意点
グループ関数を使用しているとき、次の句に指定できるのは、グループ関数またはGROUP BY
句で指定した列に限られます。
-
SELECT
句 -
HAVING
句 -
ORDER BY
句