Hitachi

Hitachi Advanced Data Binder SQLリファレンス


7.7.1 GROUP BY句の指定形式および規則

グループごとに検索データを集計する場合にGROUP BY句を指定します。

〈この項の構成〉

(1) 指定形式

GROUP BY句::=GROUP BY 〔グループ化方式指定グループ化指定〔,グループ化指定〕…
 
  グループ化方式指定::=/*>> WITHOUT GLOBAL HASH GROUPING <<*/
  グループ化指定::=値式 〔〔AS〕 列名

(2) 指定形式の説明

グループ化方式指定
グループ化方式指定::=/*>> WITHOUT GLOBAL HASH GROUPING <<*/

グループ化方式指定を指定した場合,グループ化の処理方式にグローバルハッシュグループ化が適用されなくなります。

通常は,この指定をする必要はありません。

グループ化の処理方式については,マニュアルHADB AP開発ガイドグループ化の処理方式を参照してください。

なお,/*>><<*/で囲んだ文字列は注釈になりません。グループ化方式指定以外を記述するとエラーになります。

グループ化指定
グループ化指定::=値式 〔〔AS〕 列名

検索データを集計する際のグループを値式の形式で指定します。値式については,「7.21 値式」を参照してください。

GROUP BY句の指定例を次に示します。

(例1)商品コード(PUR-CODE)ごとにデータを集計する場合
GROUP BY "PUR-CODE"
(例2)月単位でデータを集計する場合
GROUP BY EXTRACT(MONTH FROM "SALE-DAY") AS "GMONTH"

SALE-DAY列には,商品の販売日がDATE型の形式で格納されています。スカラ関数EXTRACTを使用して,SALE-DAY列の月の部分を抽出しています。

〔AS〕 列名

ここで指定した列名がグループ化列名になります。

(例)

GROUP BY SUBSTR("C1",5,2) AS "GC1"

上記の例の場合,GC1がグループ化列名になります。

メモ

GROUP BY句の結果,導出される列をグループ化列といいます。また,グループ化列に付けられた列名をグループ化列名といいます。

(例1)

GROUP BY "C1"

上記の例の場合,下線部分がグループ化列になり,グループ化列名はC1になります。

(例2)

GROUP BY "T1"."C1"

上記の例の場合,下線部分がグループ化列になり,グループ化列名はC1になります。

(例3)

GROUP BY "C1" AS "GC1"

上記の例の場合,下線部分がグループ化列になり,グループ化列名はGC1になります。

(例4)

GROUP BY SUBSTR("C1",5,2) AS "GC1"

上記の例の場合,下線部分がグループ化列になり,グループ化列名はGC1になります。

(例5)

GROUP BY SUBSTR("C1",5,2)

上記の例の場合,下線部分がグループ化列になり,グループ化列名はなしとなります。

(例6)

GROUP BY "C1","C2"

上記の例の場合,下線部分がグループ化列になります(グループ化列が2つになります)。グループ化列名はC1C2になります。

(例7)

GROUP BY 1 AS "GC1"

上記の例の場合,下線部分がグループ化列になり,グループ化列名はGC1になります。

(例8)

GROUP BY 1

上記の例の場合,下線部分がグループ化列になり,グループ化列名はなしとなります。

(3) 規則

  1. グループ化列の数の上限は64個になります。

  2. 式中に集合関数は指定できません。

  3. 式中に副問合せは指定できません。

  4. 式中に?パラメタは指定できません。

  5. 値式には配列データを指定できません。

  6. ほかのグループ化列に単独で指定した列指定と同じ列名を,「AS 列名」に指定できません。

    (例)エラーになる指定例

    GROUP BY "C1","C3" AS "C1"
    GROUP BY "C1" AS "C2","C3" AS "C1"
  7. HADBによって自動的に設定される導出列名と重複する可能性があるため,グループ化指定の「AS 列名」の列名にEXPnnnn_NO_NAMEを指定しないでください。nnnnは,00009999の符号なし整数です。

  8. AS 列名」に指定する列名は,重複して指定できません。

    (例)エラーになる指定例

    GROUP BY "C1"+1 AS "GC1","C2"+1 AS "GC1"
  9. AS 列名」に指定した列名を,選択式中の副問合せ,またはHAVING句中の副問合せから参照することはできません。

    (例)エラーになる指定例

    SELECT "GC1",MAX("C2") FROM "T1"
        GROUP BY SUBSTR("C1",5,2) AS "GC1"
        HAVING EXISTS(SELECT * FROM "T2" WHERE "T2"."C1"="GC1")
  10. GROUP BY句を指定した場合,次に示す項目だけが選択式に指定できます。

    1. グループ化列名

    2. 集合関数

    3. 値指定

    4. スカラ副問合せ

    5. 1.〜4.を指定した値式

    6. グループ化指定に指定した値式(列指定を含む値式)と同じ値式

    (例)正しい指定例

    SELECT "C1","C2",COUNT(*)選択式にグループ化列名と集合関数が指定されている
        FROM "T1"
            GROUP BY "C1","C2"

    (例)エラーになる指定例

    SELECT "C1","C2",COUNT(*)選択式にグループ化列名ではないC2列が指定されている
        FROM "T1"
            GROUP BY "C1"
  11. GROUP BY句中に指定する列指定は,次の条件を満たす必要があります。

    • GROUP BY句を指定した表式中のFROM句に指定している表の列を指定する

    • 列名は一意に識別できるように指定する

    次に示すSELECT文を実行した場合を例にして具体的に説明します。

    (例)

    SELECT "SALESLIST"."USERID",SUM("PUR-NUM")
        FROM "SALESLIST","USERSLIST"
            WHERE "PUR-CODE"='P002'
            AND "SALESLIST"."USERID"="USERSLIST"."USERID"
            GROUP BY "SALESLIST"."USERID"

    販売履歴表(SALESLIST)と顧客表(USERSLIST)には,同じ列名のUSERID列があります。このようなケースで,GROUP BY句にUSERID列を指定する場合,どちらのUSERID列のことなのか一意に識別できるように指定する必要があります。そのため,GROUP BY "USERID"とは指定できません。GROUP BY "SALESLIST"."USERID"のように表名で修飾するようにしてください。

  12. 選択式の値式中,またはHAVING句の値式中に指定した列が参照するグループ化列は,次に示す優先順位に従って決定されます。番号が小さいほど優先順位が高くなります(1.がいちばん優先順位が高くなります)。

    1. グループ化列名に同じ列名がある場合

    (例)正しい指定例

    SELECT "C1"+"C2" FROM "T1" GROUP BY "C1"+"C2" AS "C1","C2"

    上記の例の場合,選択式中のC1は,グループ化列名に同じ名称のC1があるため,グループ化列「"C1"+"C2" AS "C1"」を参照します。

    選択式中のC2は,グループ化列名に同じ名称のC2があるため,グループ化列C2を参照します。

    2. 単独の列指定のグループ化列がある場合,または値式の形式が同じであるグループ化列がある場合

    (例1)正しい指定例

    SELECT "C1"+"C2" FROM "T1" GROUP BY "C1"+"C2" AS "C3"

    上記の例の場合,選択式中のC1C2は,値式の形式が同じであるグループ化列「"C1"+"C2" AS "C3"」があるため,グループ化列「"C1"+"C2" AS "C3"」を参照します。

    (例2)正しい指定例

    SELECT "GC1","C1" FROM "T1" GROUP BY "C1" AS "GC1"

    上記の場合,選択式中のC1は値式の形式が同じであるグループ化列「"C1" AS "GC1"」を参照します。

    また,選択式中のGC1はグループ化列名に同じ名称のGC1があるため,上記の指定例は「1. グループ化列名に同じ列名がある場合」の条件にも該当します。そのため,GC1も,グループ化列「"C1" AS "GC1"」を参照します。

    3. グループ化列の指定順(前方優先)

    (例)正しい指定例

    SELECT "C1"+"C2" FROM "T1" GROUP BY "C1"+"C2" AS "C3","C1"+"C2"

    上記の例の場合,グループ化列の値式の形式が「"C1"+"C2" AS "C3"」と「"C1"+"C2"」で同じになります。この場合,前方優先となるため,選択式中のC1C2は,グループ化列「"C1"+"C2" AS "C3"」を参照します。

    ■エラーになる指定例

    SELECT "C1"+"C2" FROM "T1" GROUP BY "C1"+"C2" AS "C1"

    上記の例の場合,選択式中のC1は,下線部分のグループ化列名C1に対応するグループ化列を参照します。一方,選択式中のC2は,同じ名称のグループ化列名がありません。そのため,上記のSQL文はエラーになります。

  13. グループ化指定の値式に指定した列名と同じ名称を,同じグループ化指定のグループ化列名に指定しないことを推奨します。グループ化指定の値式に指定した列名とグループ化列名が同じ場合,意図しないグループ化列を参照するおそれがあります。

    (例)

    SELECT "C1"+1 FROM "T1" GROUP BY "C1"+1 AS "C1"

    上記の例の場合,グループ化指定の値式中にC1を指定し,グループ化列名にもC1を指定しています。この場合,選択式中のC1は,グループ化列「"C1"+1 AS "C1"」を参照します。

  14. 選択式中の副問合せ,またはHAVING句中の副問合せからは,グループ化列として指定した列指定を含む値式を参照できません。

    (例)エラーになる指定例

    SELECT "T1"."C1"+"T1"."C2" FROM "T1"
        GROUP BY "T1"."C1"+"T1"."C2"
        HAVING (SELECT "T2"."C1" FROM "T2"
                   WHERE "T2"."C1" > "T1"."C1"+"T1"."C2") > 0

    HAVING句中の副問合せに指定した「"T1"."C1"+"T1"."C2"」は,グループ化列「"T1"."C1"+"T1"."C2"」を参照できません。そのため,上記のSQL文はエラーになります

  15. WHERE句の結果がGROUP BY句に適用されてグループ化されます。表式の結果が導き出される順序については,「7.4.1 表式の指定形式および規則」の「(3) 規則」を参照してください。

  16. 先行するWHERE句の結果をTとします(WHERE句が指定されていない場合は,先行するFROM句の結果をTとします)。

    • GROUP BY句を指定した場合,集合Tが複数のグループに分けられます(グループ化列の値が同じである集合を1つのグループとします)。その際,各グループのグループ化列の重複行が排除されるため,GROUP BY句の結果の行は,作成されたグループ数と同じになります。

      なお,グループ化列にナル値がある場合は,ナル値同士を同じ値として1つのグループにします。

    • GROUP BY句を省略して,その問合せ指定中にHAVING句または集合関数を指定した場合,T全体で構成される1つのグループが作成されます。

(4) 例題

例題1

販売履歴表(SALESLIST)から,顧客ごとの商品購入回数の一覧を求めます。

SELECT "USERID",COUNT(*) AS "COUNT"
    FROM "SALESLIST"
        GROUP BY "USERID"

下線部分がGROUP BY句の指定です。

実行結果の例

[図データ]

例題2

販売履歴表(SALESLIST)から,2011/9/3以降の商品コード(PUR-CODE)ごとの販売個数の合計値,平均値を求めます。

SELECT "PUR-CODE",SUM("PUR-NUM") AS "SUM",AVG("PUR-NUM") AS "AVG"
    FROM "SALESLIST"
        WHERE "PUR-DATE">=DATE'2011-09-03'
        GROUP BY "PUR-CODE"

下線部分がGROUP BY句の指定です。

実行結果の例

[図データ]

例題3

販売履歴表(SALESLIST)と顧客表(USERSLIST)から,2011/9/4以降の商品コードP002の販売個数(PUR-NUM)の合計値を顧客ごとに求めます。

SELECT "NAME",SUM("PUR-NUM") AS "SUM"
    FROM "SALESLIST","USERSLIST"
        WHERE "PUR-DATE">=DATE'2011-09-04'
        AND "PUR-CODE"='P002'
        AND "SALESLIST"."USERID"="USERSLIST"."USERID"
        GROUP BY "NAME"

下線部分がGROUP BY句の指定です。

実行結果の例

[図データ]

例題4

社員表(EMPLIST)から,年齢を10歳単位のグループに分けて,グループごとの社員数を求めます。60歳以上は60歳のグループに属するようにします。

SELECT "GAGE",COUNT(*) AS "COUNT"
    FROM "EMPLIST"
        GROUP BY CASE WHEN "AGE">=60 THEN 60 
                      ELSE TRUNC("AGE",-1)
                 END AS "GAGE"

下線部分がGROUP BY句の指定です。

実行結果の例

[図データ]

例題5

販売履歴表(SALESLIST)から,2013年の売り上げ金額を月単位で求めます。

  • SALE-DAY列には,商品の販売日がDATE型の形式で格納されています。

  • AMOUNT列には,顧客が商品を購入した際の購入金額が格納されています。

SELECT "GMONTH",SUM("AMOUNT") AS "SUM"
    FROM "SALESLIST"
        WHERE EXTRACT(YEAR FROM "SALE-DAY")=2013
        GROUP BY EXTRACT(MONTH FROM "SALE-DAY") AS "GMONTH"

下線部分がGROUP BY句の指定です。

実行結果の例

[図データ]

(5) 留意事項

  1. GROUP BY句を指定した場合,作業表が作成されることがあります。作業表が作成される作業表用DBエリアの容量が正しく見積もられていない場合,性能低下の原因となることがあります。作業表用DBエリアの容量見積もりについては,マニュアルHADB システム構築・運用ガイドを参照してください。作業表の詳細については,マニュアルHADB AP開発ガイド作業表が作成されるSQLを実行する際の考慮点を参照してください。

  2. グループ化の処理方式にグローバルハッシュグループ化が適用された場合,適切な大きさのハッシュテーブル領域が必要になります。ハッシュテーブル領域の大きさはサーバ定義またはクライアント定義のadb_sql_exe_hashtbl_area_sizeオペランドで指定します。

    また,グループ化の処理方式にローカルハッシュグループ化が適用された場合,適切な大きさのハッシュグループ化領域が必要になります。ハッシュグループ化領域の大きさはサーバ定義またはクライアント定義のadb_sql_exe_hashgrp_area_sizeオペランドで指定します。

    グループ化の処理方式については,マニュアルHADB AP開発ガイドを参照してください。