ヘッダーをスキップ

Oracle Rdb SQLリファレンス・マニュアル リリース7.2 E06178-01 |
| 目次 | 索引

戻る | 次へ |

# 2.8 選択式および列選択式

SQL構文の2つの基本要素は、選択式と列選択式です。選択式は結果表を指定し、列選択式はスカラー値を返します。結果表とは、式のFROM句で識別される表参照の一部の組合せから派生する中間表のことです。表参照は、実表、ビュー、派生表または結合表です。

選択式は、SELECT文、DECLARE CURSOR文、FORカーソル・ループ、CREATE VIEW文およびINSERT...SELECT文の基礎となります。選択式は、データベースから取得される結果表か、またはデータベースに格納される結果表を指定し、また、式のFROM句で識別される表参照の一部の組合せから派生します。

列選択式は、1列の結果表を指定する選択式であり、条件および（単一値を指定する場合は）値式内でネストできます。

表2-36は、選択式および列選択式が他の文でどのように使用されるかを示しています。この項のこれ以降では、選択式および列選択式について詳細に説明します。

表2-36 異なる形式の選択式の概要
形式 | 使用方法 | 説明 | 別名
--- | --- | --- | ---
SELECT文 | 一般的な対話型または動的に使用する制限が最も少ない形式。詳細は、「SELECT文: 一般形式」を参照。 | 選択式 |
選択式 | SELECTの基本形。使用先: SELECT DECLARE CURSOR CREATE VIEW INSERT...SELECT | 第2.8.1項を参照 | 問合せ指定（ANSI/ISO SQL）
列選択式 | 条件内のSELECT式であり、値式として使用する。 | 選択リストのない選択式。条件内では、結果表の幅が単一列である必要がある（EXISTS条件およびSINGLE条件を除く）。値式として使用する場合は、結果表に単一値を含める必要がある。 | 副問合せ（ANSI/ISO SQL）
シングルトン選択 | ホスト言語プログラム内のSELECT文であり、値の単一行をホスト言語変数に割り当てる。詳細は、「SELECT文: シングルトン選択」を参照。 | SELECTリストの後にINTO句を指定した選択式。結果表は単一行である必要がある。 | 選択文（ANSI/ISO SQL）

## 2.8.1 選択式

選択式を使用すると、次の4種類の結果表を定義できます。

- 単純表

- 集計表

- 結合表

- 派生表

単純表の結果は単純表またはビューから生成され、通常は特殊なDBKEY列が含まれています。このような表の行は、権限があれば更新できます。

集計表は、GROUP BY句（複数行の結果が有効）によって形成される仮想表またはGROUP BY句が無効（単一行の結果）な集計（または統計）式です。

表参照は、実表、ビュー、派生表または結合表です。

派生表は、選択式を評価することによって取得されるデータを表す名前付きの仮想表です。派生表は、指定される相関名によって名前が付けられます。派生表およびその列は、相関名を使用する問合せ内で参照できます。派生表は、定義に使用される選択式によって表される仮想表でもあるという点でビューに類似しています。つまり、派生表はFROM句内で定義が指定されるビューに類似しています。

結合表は、2つの表参照を結合することによって取得されるデータを表す仮想表です。2つの表参照間の結合タイプは、CROSS、INNER JOIN、LEFT OUTER JOIN、RIGHT OUTER JOIN、FULL OUTER JOINのいずれかです。外部結合操作を指定するには、結合表の構文を使用する必要があります。

結合表には、次の2種類があります。

- 修飾結合

- クロス結合

結合表と派生表の詳細は、次の構文および引数を参照してください。

Oracle形式の結合表の詳細は、付録Gを参照してください。

環境

選択式は、対話型SQLまたはホスト言語プログラムで、それ自体または他のSQL文の一部として使用できます。

SQLでは、選択句の引数は次の順序で評価されます。

1. FROM

2. WHERE

3. GROUP BY

4. HAVING

5. 選択リスト

6. ORDER BY

7. LIMIT TO

これらのそれぞれの句の後に、次の句の評価に使用する中間結果表が作成されます。オプティマイザでは、結果を変更せずにこの処理を最も迅速に行う方法が決定されます。

形式

## 引数

> ### AS name

> オプションとして、AS句では名前が付けられない列に対して名前を付けることができます。次に例を示します。

>     SQL> SELECT JOB_CODE AS JOB,
>     cont> MAXIMUM_SALARY - MINIMUM_SALARY AS RANGE
>     cont> FROM JOBS
>     cont> WHERE JOB_CODE LIKE 'S%';
>      JOB                     RANGE
>      SANL                 20000.00
>      SCTR                 15000.00
>      SPGM                 25000.00
>     3 rows selected

> 選択リスト内のワイルドカードとしてアスタリスク（*）を使用できます。

> デリミタ付き識別子を使用するには、SQL99または同様の言語を指定するか、これらの言語に対してSET QUOTING RULES文を使用する必要があります。

> ### ASC

> ### DESC

> ソート・キーの値を昇順または降順のどちらでソートするかを決定します。

> ソート・キーのソート順を指定しない場合、デフォルトは昇順です。

> 言語がSQLV40（デフォルト言語）に設定されている場合は、前のソート・キーからソート順が継承されます。

> ### correlation-name-clause

> 表またはビューに続いて相関名を指定できますが、選択式の他の部分で列名を修飾するには、派生表に対してFROM句で相関名を指定する必要があります。相関名を明示的に指定しない場合は、SQLによって表名またはビュー名が相関名として暗黙的に指定されます。明示的または暗黙的のどちらでも、同じ相関名を複数回指定することはできません。

> 派生表で相関名を指定すると、列名も変更されることがあります。したがって、相関名の左にある表の列数は、相関名の右で指定する列数と一致している必要があります。

> ### CORRESPONDING

> UNION演算子、EXCEPT演算子、MINUS演算子およびINTERSECT演算子をキーワードCORRESPONDINGの後に続けることができます。これによって、select-merge-clauseの2つの選択リストが名前で比較されます。結果として得られる問合せ表には、両方のリストに存在する列名のみが保持されます。

> 名前は、列名またはAS句で指定された名前のいずれかになります。共通の名前が存在しないか、選択リストに同じ列名が複数回存在する場合は、エラーが通知されます。

> ### CROSS JOIN

> 左側で指定された表参照のすべての行を、結果の右側で指定された表参照のすべての行に結合します。クロス結合は2つの表参照間のデカルト積です。クロス結合は基本結合式に類似していますが、WHERE句はありません。これもデカルト積と呼ばれます。次に、カンマ区切り構文を使用した基本結合式の例を示します。

>     SQL> SELECT *
>     cont>   FROM TABLE1, TABLE2;

> CROSS JOIN句を使用すると、前の例は次のようになります。

>     SQL> SELECT *
>     cont>   FROM TABLE1 CROSS JOIN TABLE2;

> ### EDIT USING edit-string

> ### EDIT USING domain-name

> 編集文字列を値式に関連付けます。domain-nameを指定すると、そのドメインに対して定義された編集文字列が使用されます。この句により、問合せで列または変数に対して定義されたEDIT STRINGはすべて無効になります。この句は対話型SQLでのみ有効です。

> 次の例は、この句の使用方法を示しています。

>     SQL> set quoting rules 'SQL99';
>     SQL>
>     SQL> create domain MONEY integer(2) edit string '$$$,$$$,$$9';
>     SQL>
>     SQL> select
>     cont>     last_name as "Last Name",
>     cont>     employee_id,
>     cont>     birthday as "Birthday" edit using 'YYYYBDDBMMM',
>     cont>     (select salary_amount
>     cont>      from salary_history sh
>     cont>      where sh.employee_id = e.employee_id
>     cont>        and salary_end is null) as "Salary" edit using MONEY
>     cont> from employees e
>     cont> where e.employee_id < '00167';
>      Last Name        EMPLOYEE_ID   Birthday           Salary
>      Toliver          00164         1947 28 Mar       $51,712
>      Smith            00165         1954 15 May       $11,676
>      MacMullan        00166         1954 20 Mar       $18,497
>     3 rows selected

> ### EXCEPT

> ### EXCEPT DISTINCT

> EXCEPT DISTINCT演算子は、最初の選択式から結果表を作成するために使用されます。ただし、2番目の選択式にも存在する行の値は除外されます。

> DISTINCTはデフォルトであるため、EXCEPTとEXCEPT DISTINCTは同一の操作です。EXCEPTは、ANSIおよびISO SQL:1999データベース言語規格に準拠しています。

> 注意 EXCEPTには可換性はありません。つまり、A EXCEPT Bの結果は、B EXCEPT Aの結果とは異なる行のセットになります。

> ### FROM derived-table

> 派生表は、FROM句の選択式の評価によって取得されるデータを含む名前付きの仮想表です。派生表は、相関名を指定すると名前が付けられます。

> 派生表の相関名を指定する必要があります。これにより、選択リストまたは後続句でユーザーが指定できる列名が決まります。選択リストまたは後続句では相関名および派生表の列名のみを参照でき、派生表を定義した表名または列名は参照できません。

> 次に、人事データベースを使用した派生表の例を示します。この例では、JOB_HISTORY表の行が3行未満の部門をすべて検索します。

>     SQL> SELECT *
>     cont> FROM (SELECT DEPARTMENT_CODE, COUNT(*)
>     cont>       FROM JOB_HISTORY
>     cont>       WHERE JOB_END IS NULL
>     cont>       GROUP BY DEPARTMENT_CODE)
>     cont>       AS DEPT_INFO (D_CODE, D_COUNT)
>     cont> WHERE D_COUNT < 3;
>      D_CODE       D_COUNT
>      ENG                2
>      MCBS               1
>      MSMG               1
>      MTEL               2
>      PERS               2
>      SUSA               2
>     6 rows selected

> ### FROM joined-table

> 結合表は、FROM句で指定された2つの表参照の結合を表します。

> 結合表には、次の2種類があります。

> - 修飾結合: 暗黙的または明示的な条件が構文に含まれる。

> - クロス結合: 条件が構文に含まれない。

> 表は、それ自体または他の表に結合できます。joined-table式で外部結合を指定する場合、カッコを使用して結合順序を明示的に定義できます。joined-table式で内部結合またはクロス結合のみを指定する場合は、カッコを使用しても結合順序には反映されません。SQLでは可能なすべての結合順序を試して、問合せに対して最も効率的な順序を検索します。joined-table式で外部結合を指定すると、カッコがあるものが最優先され、次に左から右のルールで結合順序が決まります。

> joined-table式で指定された表名または相関名は、外部選択式で参照できます。

> ### FROM table-name

> ### FROM view-name

> SQLで結果表の生成に使用される表およびビューを識別します。複数の表またはビューを指定すると、それが結合されて1つの中間結果表が作成されます。

> ### FULL OUTER JOIN

> 左側で指定された表参照のすべての行、および結果の右側で指定された表参照のすべての行を保持します。対応する列に一致する値が存在しない場合は、列にNULLが表示されます。次に例を示します。

>     SQL> SELECT *
>     cont> FROM TABLE1 FULL OUTER JOIN TABLE2
>     cont> ON TABLE1.C1 = TABLE2.C1;
>        TABLE1.C1     TABLE1.C2     TABLE2.C1   TABLE2.C4
>               10            15            10   AA
>             NULL          NULL            15   BB
>               20            25            20   CC
>               30            35          NULL   NULL
>     4 rows selected

> FULL OUTER JOIN句のON句では、少なくとも1つの等価結合条件を指定する必要があります。この制限は、USING句を指定したFULL OUTER JOIN句またはNATURAL FULL OUTER JOIN句には適用されません。

> 等価結合では、等号（=）を使用すると、1つの表に存在する列の値と別の表の対応する列の値が暗黙的に一致します。

> ### GROUP BY value-expr

> WHERE句（指定されている場合）またはFROM句の中間結果表を構成するためにSQLで使用される値式を指定します。同じ値を含む行のグループをコントロール・ブレークとも呼びます。

> GROUP BY句で指定された最初の式では、前の中間結果表の行が、指定の式に対して同じ値を持つ行にグループ化されます。GROUP BY句に2つ目の式が指定されていると、各メイン・グループ内で、2つ目の式の値によって行がグループ化されます。GROUP BY句の他の列についても、同様にグループ化されます。

> GROUP BY句にある列名がNULL値のものは、すべてまとめてグループ化されます。

> 各グループは、結果表の単一行の値に対するソースとして処理されます。

> グループのすべての行は、GROUP BY句で指定された値式に対して同じ値を持つため、値式または条件でのその列の参照では、単一値が指定されます。

> ### HAVING predicate

> 中間結果表を生成するためにSQLで評価される条件を指定します。条件は、前の句で作成された中間結果表のグループごとに評価されます。条件がTRUEとなった表のグループは、選択リストの評価対象となる別の中間結果表になります。

> HAVING句の前にある句がGROUP BY句の場合、条件は、中間結果表のグループごとに評価されます。WHERE句が個々の行に影響を与えるのと同様に、HAVING句はグループに影響を与えます。

> HAVING句の前にGROUP BY句が存在しない場合は、単一グループとしての中間結果表のすべての行に対して条件が評価されます。

> HAVING句の条件に指定できる式には制限があります。HAVING条件の列名または式は、次のいずれかの基準を満たしている必要があります。

> - GROUP BY句にも存在していること。

> - 集計関数内で指定されていること。

> - 外部参照であること（HAVING句が列選択式の一部である場合にのみ可能）。

> たとえば、次の文は無効です。HAVING句にGROUP BY句が指定されていないため、HAVING句の列名はファンクションの一部である必要があります（外部問合せがなく、列名が外部参照とならないため）。

>     SQL> SELECT LAST_NAME, FIRST_NAME FROM EMPLOYEES
>     cont> HAVING FIRST_NAME = 'Bob';
>     %SQL-F-NOTGROFLD, Column FIRST_NAME cannot be referred to in
>     the select list or HAVING clause because it is not in the GROUP BY clause

> ### INNER JOIN

> 左側で指定された表参照のすべての行を、右側で指定された表参照の一致する行に結合します。次に例を示します。

>     SQL> SELECT *
>     cont> FROM TABLE1 INNER JOIN TABLE2
>     cont> ON TABLE1.C1 = TABLE2.C1
>     cont> AND C2 BETWEEN 25 AND 35;
>        TABLE1.C1     TABLE1.C2     TABLE2.C1   TABLE2.C4
>               10            15            10   AA
>               20            25            20   CC
>     2 rows selected

> TABLE1およびTABLE2はいずれも選択句の残りの部分で公開されるため、どちらの表参照からでも列を修飾するために使用できます。

>     SQL> SELECT *
>     cont> FROM TABLE1 INNER JOIN TABLE2
>     cont> ON TABLE1.C1 = TABLE2.C1
>     cont> WHERE TABLE1.C1 = 10;
>        TABLE1.C1     TABLE1.C2     TABLE2.C1     TABLE2.C4
>               10            15            10            AA
>     1 row selected

> joined-table式でINNER JOINを指定すると、表参照の結合順序が暗黙的に指定されます。たとえば、A INNER JOIN B INNER JOIN CはA INNER JOIN C INNER JOIN Bと同じです。通常、内部結合の表参照にある表参照A、BおよびCは、どのように組み合せても同じ結果になります。また、SELECT * FROM A INNER JOIN B ON P1 INNER JOIN C ON P2は、構文SELECT * FROM A, B, C WHERE P1 AND P2と同じです。

> ### INTERSECT

> ### INTERSECT DISTINCT

> INTERSECT DISTINCT演算子は、最初の選択式から、2番目の選択式にも存在する行の値について結果表を作成するために使用されます。

> DISTINCTはデフォルトであるため、INTERSECTとINTERSECT DISTINCTは同一の操作です。INTERSECTは、ANSIおよびISO SQL:1999データベース言語規格に準拠しています。

> 注意 通常、INTERSECTには可換性があります。つまり、A INTERSECT Bの結果の行セットは、B INTERSECT Aと同じ行のセットになります。これを下の例に示します。ただし、INTERSECTの異なるブランチでLIMIT TOを使用する場合は、Rdbオプティマイザで異なるソリューション計画が使用されている可能性があり、決定的な結果が得られないため注意が必要です。

> ### LEFT OUTER JOIN

> 左側で指定された表参照のすべての行を保持すると、結果の右側で指定された表参照の行と一致します。右側で指定された表に一致する列が存在しない場合は、NULLが表示されます。次に例を示します。

>     SQL> SELECT *
>     cont> FROM TABLE1 LEFT OUTER JOIN TABLE2
>     cont> ON TABLE1.C1 = TABLE2.C1;
>        TABLE1.C1     TABLE1.C2     TABLE2.C1   TABLE2.C4
>               10            15            10   AA
>               20            25            20   CC
>               30            35          NULL   NULL
>     3 rows selected

> 外部結合は基本的に、一致しないすべての行にNULLを追加する共用体を使用する内部結合です。LEFT OUTER JOINの例は、INNER JOINの例の結果に一致しない行を追加したものと同じになります。

> ON句で指定された検索条件は、外部結合結果の構成に使用されます。結合条件のみでなく、選択条件および副問合せもON句で指定できます。次に例を示します。

>     SQL> SELECT *
>     cont> FROM TABLE1 LEFT OUTER JOIN TABLE2
>     cont> ON TABLE1.C1 = TABLE2.C1
>     cont> AND C2 BETWEEN 25 AND 35;
>        TABLE1.C1     TABLE1.C2     TABLE2.C1   TABLE2.C4
>               10            15          NULL   NULL
>               20            25            20   CC
>               30            35          NULL   NULL
>     3 rows selected

> ON句の選択条件により、内部結合結果が削減されます。左側の外部結合結果には、内部結合結果に加え、TABLE2の行と一致しないTABLE1の各行がNULLで拡張されたものが含まれています。

> 一方、次の例の結果では、選択条件は同じですがWHERE句を使用しています。

>     SQL> SELECT *
>     cont> FROM TABLE1 LEFT OUTER JOIN TABLE2
>     cont> ON TABLE1.C1 = TABLE2.C1
>     cont> WHERE C2 BETWEEN 25 AND 35;
>        TABLE1.C1     TABLE1.C2     TABLE2.C1   TABLE2.C4
>               20            25            20   CC
>               30            35          NULL   NULL
>     2 rows selected

> 前の例では、ON句の検索条件を使用して、左側の外部結合結果が最初に構成されます。次に、外部結合結果の各行にWHERE句の選択条件が適用され、最終結果が形成されます。

> ### LIMIT TO limit-expression

> ### LIMIT TO skip-expression

> LIMIT TO句を使用すると、結果表に含まれる行数を制限するか、問合せから返される行をスキップできます。たとえば、結果セットの最初の行が、RMU/LOAD/RECORD=FORMAT=DELIMITEDコマンドでロードされたCSVデータ・ソースからロードされる列ヘッダーになる場合がありますが、これは問合せで無視されます。

> limit-expressionまたはskip-expressionを数値リテラルとして指定する場合、スケールなしの値を指定する必要があります。この数式は、問合せの実行前にBIGINTに変換されます。

> limit-expressionおよびskip-expressionでは、それが存在するselect-expressionからは列を参照できません。使用できる列は、limit-expressionまたはskip-expressionに対して指定した副選択の列のみです。この項の例では、LIMIT TO句で副選択を使用しています。

> 注意 パフォーマンス上の理由により、skip-expressionには小さい値を指定することをお薦めします。スキップされた行はアプリケーションには返されませんが、問合せによってフェッチされ、処理されます。

> limit-expressionが負の値またはゼロと評価されると、問合せから行が返されず、エラーも通知されません。

> skip-expressionが負の値またはゼロと評価されると、行はスキップされません。skip-expressionが結果セットの行より大きいと、問合せから行が返されず、エラーも通知されません。次の例は、LIMIT TO ...SKIP構文の使用方法を示しています。

> この問合せからは、EMPLOYEES表の100番目の従業員が返されます。

>     SQL> select last_name, first_name, employee_id
>     cont> from employees
>     cont> order by employee_id
>     cont> limit to 1 skip 99 rows;
>      LAST_NAME        FIRST_NAME   EMPLOYEE_ID
>      Herbener         James        00471
>     1 row selected

> ソートされたリストの最後の行を取得するには、次の例に示すように、値を計算する副選択でリテラル値を置換します。この問合せでは、問合せ計画に対するSET FLAGSコマンドの出力も示しています。

>     SQL> set flags 'strategy,detail';
>     SQL> select last_name, first_name, employee_id
>     cont> from employees
>     cont> order by employee_id
>     cont> limit to 1
>     cont> skip (select count(*)-1 from employees) rows;
>     Tables:
>       0 = EMPLOYEES
>       1 = EMPLOYEES
>     Cross block of 2 entries
>       Cross block entry 1
>         Aggregate: 0:COUNT (*)
>         Index only retrieval of relation 1:EMPLOYEES
>           Index name  EMP_EMPLOYEE_ID [0:0]
>       Cross block entry 2
>         Firstn: 1
>         Skipn: <agg0> - 1
>         Get     Retrieval by index of relation 0:EMPLOYEES
>           Index name  EMP_EMPLOYEE_ID [0:0]
>      LAST_NAME        FIRST_NAME   EMPLOYEE_ID
>      Herbener         James        00471
>     1 row selected
>     SQL>

> この問合せの代替として、ORDER ... DESCを使用してから、LIMIT 1 ROW句を使用します。

> この問合せでは、統計的な給与中間値を検出します。

>     SQL> -- select the median salary
>     SQL> select salary_amount
>     cont> from salary_history
>     cont> where salary_end is NULL
>     cont> order by salary_amount
>     cont> limit to 1
>     cont> skip (select count(*)/2
>     cont>       from salary_history
>     cont>       where salary_end is NULL);
>      SALARY_AMOUNT
>         $24,166.00
>     1 row selected
>     SQL>

> この結果は平均給与と比較できます。

>     SQL> -- select the median salary compare with average
>     SQL> select salary_amount as median_salary,
>     cont>        (select avg (salary_amount)
>     cont>         from salary_history
>     cont>         where salary_end is NULL) as avg_salary edit using SALARY
>     cont> from salary_history
>     cont> where salary_end is NULL
>     cont> order by salary_amount
>     cont> limit to 1
>     cont> skip (select count(*)/2
>     cont>       from salary_history
>     cont>       where salary_end is NULL);
>      MEDIAN_SALARY    AVG_SALARY
>         $24,166.00    $31,922.79
>     1 row selected
>     SQL>

> ### MINUS

> MINUS演算子はEXCEPT DISTINCT演算子のシノニムであり、Oracle RDBMS SQL言語との言語互換性のために提供されています。

> ### NATURAL JOIN

> 指定された表の一致する名前付き列で、等価結合操作を実行します。等価結合では、等号（=）を使用すると、1つの表に存在する列値と別の表の対応する列値が暗黙的に一致します。