GROUP BY句

GROUP BY句はSELECT文で使用して、複数行にわたるデータを収集し、結果を1つ以上の列または式でグループ化します。GROUP BY句は、多くの場合、集計関数とともに使用します。Oracle NoSQL Databaseでは、集計関数が行の各グループに適用され、グループごとに1行が返されます。

構文

groupby_clause ::= GROUP BY expression ("," expression)*

セマンティクス

各(グループ化)式は、最大で1つのアトミック値を返す必要があります。グループ化式が入力行に対して空の結果を返す場合、その行はスキップされます。グループ化値間の等価性は、=演算子のセマンティクスに従って定義されます。ただし、2つのNULL値は等しいとみなされます。値の比較演算子の項を参照してください。次に、グループごとに、GROUP BY句によって単一のレコードが作成されて返されます。この句にN個のグループ化式がある場合は、返されたレコードの最初のN個のフィールドに、グループ化式の値が格納されます。残りのM個のフィールド(m >= 0)には、ゼロ個以上の集計関数の結果が格納されます。一般に集計関数は、グループの行を反復し、該当する各行の式を評価し、返された値をグループごとに1つの値に集計します。Oracle NoSQL Databaseでは、集計関数の使用の項で説明されているような多くの集計関数がサポートされます。

構文的には、集計関数は実際にはGROUP BY句にリストされませんが、SELECT句には表示されます。実際、集計関数はSELECT句またはORDER BY句にのみ表示され、ネストすることはできません。ただし、意味的にはSELECTリストまたはORDER BYリストに表示される各集計関数は、実際にはGROUP BY句によって評価されます。SELECT句に集計関数が含まれていても、SELECT式にGROUP BY句が含まれていない場合は、FROM句またはWHERE句で生成されたすべての行が1つのグループとみなされ、集計関数がこの1つのグループ全体に対して評価されます。

GROUP BY句の実装は、索引ベースまたは汎用です。索引ベースのグループ化が可能なのは、グループ化式の値で行をソートする索引が存在する場合のみです。単純索引の項を参照してください。より正確には、e1、e2、…、eN (eii番目の式(iは1、2、3、...Nの範囲の数値))をGROUP BY句に表示されるとおり(左から右)にグループ化式とします。次に、索引ベースのグループ化の場合、1、2、...、Nの各iについてeii番目の索引フィールドの定義に一致する索引(主キー索引または既存の2次索引の1つ)が存在する必要があります。このような索引が存在しない場合または問合せオプティマイザによって選択されていない場合、GROUP BYは汎用になります。汎用GROUP BYは、ハッシュ表を使用して同じグループに属する行を検索し、結果をアプリケーションに返す前にすべてのグループを格納します。ハッシュ表はクライアント・ドライバ・メモリーに格納されます(サイズが制限されたローカル・ハッシュ表もサーバーで使用できます)。その結果、汎用GROUP BYは大量のドライバ・メモリーを消費する可能性があります。一方、索引ベースのグループ化は、索引によって提供される行ソートを利用して、中間結果のマテリアライズおよびキャッシュを回避します。したがって、GROUP BY問合せで使用するのに適切な索引を作成することをお薦めします。問合せの最適化での索引の使用を参照してください。最後に、索引ベースのグループ化を使用する場合、グループ化SELECT式の結果はグループ化式に基づいて順序付けられることに注意してください。

例6-4 GROUP BY句

この問合せは、ユーザーを年齢別にグループ化し、グループごとに、そのグループのユーザーの年齢と平均収入を返します。グループ化は、年齢列に2次索引(または、通常は、最初の列が年齢列である複数列索引)がある場合にのみ可能です。

SELECT 
age, 
count(*) AS count, 
avg(income) AS income 
FROM users 
GROUP BY age;