APPLYは、変種のANSI CROSS JOINまたはANSI LEFT OUTER JOINであり、左相関(left correlation)クエリをサポートします。APPLYには2つの形式があります:1つはOUTER APPLY、もう1つはCROSS APPLYです。
CROSS APPLYはCROSS JOINに似ていますが、右側で左テーブルの列を参照できます(つまり、左相関です)。table_referenceまたはcollection_expressionによって生成された結果セットの行が存在する、結合の左側のテーブルのみを返します。OUTER APPLYはLEFT OUTER JOINに似ており、右側にマッチする値がなくても左テーブルの行を保持します。
APPLY 右テーブル制約
APPLY 制約:
table_reference(テーブル参照):通常のテーブル、インラインビュー(つまりサブクエリビュー)、TABLE() が指定できます。collection_expression(コレクション式):サブクエリ、列、関数、コレクション構築子を指定できます。collection_expressionの要件:ネストされたテーブルまたは可変配列であるため、型はコレクション値でなければなりません。
使用例
テーブル t1 と t2 を作成し、いくつかのデータを挿入します。
CREATE TABLE t1 (c1 INT, c2 INT);
CREATE TABLE t2 (c1 INT, c2 INT);
INSERT INTO t1 VALUES (1, 10);
INSERT INTO t1 VALUES (2, 20);
INSERT INTO t1 VALUES (3, 30);
INSERT INTO t2 VALUES (1, 100);
INSERT INTO t2 VALUES (1, 101);
INSERT INTO t2 values (1, 102);
INSERT INTO t2 VALUES (2, 200);
右テーブルが通常のテーブルの場合、CROSS APPLY のクエリ結果は次のとおりです:
obclient > SELECT * FROM t1 cross apply t2;
+------+------+------+------+
| C1 | C2 | C1 | C2 |
+------+------+------+------+
| 1 | 10 | 1 | 100 |
| 2 | 20 | 1 | 100 |
| 3 | 30 | 1 | 100 |
| 1 | 10 | 1 | 101 |
| 2 | 20 | 1 | 101 |
| 3 | 30 | 1 | 101 |
| 1 | 10 | 2 | 200 |
| 2 | 20 | 2 | 200 |
| 3 | 30 | 2 | 200 |
| 1 | 10 | 1 | 102 |
| 2 | 20 | 1 | 102 |
| 3 | 30 | 1 | 102 |
+------+------+------+------+
右テーブルが通常のテーブルの場合、OUTER APPLY のクエリ結果は次のとおりです:
obclient > SELECT * FROM t1 outer apply t2;
+------+------+------+------+
| C1 | C2 | C1 | C2 |
+------+------+------+------+
| 1 | 10 | 1 | 100 |
| 1 | 10 | 1 | 101 |
| 1 | 10 | 1 | 102 |
| 1 | 10 | 2 | 200 |
| 2 | 20 | 1 | 100 |
| 2 | 20 | 1 | 101 |
| 2 | 20 | 1 | 102 |
| 2 | 20 | 2 | 200 |
| 3 | 30 | 1 | 100 |
| 3 | 30 | 1 | 101 |
| 3 | 30 | 1 | 102 |
| 3 | 30 | 2 | 200 |
+------+------+------+------+
右テーブルがサブクエリの場合、CROSS APPLY のクエリ結果は次のとおりです:
obclient> SELECT * FROM t1 cross apply (SELECT * FROM t2 WHERE t1.c1 = t2.c1 AND rownum <= 2) v;
+------+------+------+------+
| C1 | C2 | C1 | C2 |
+------+------+------+------+
| 1 | 10 | 1 | 100 |
| 1 | 10 | 1 | 101 |
| 2 | 20 | 2 | 200 |
+------+------+------+------+
右テーブルがサブクエリの場合、OUTER APPLY のクエリ結果は次のとおりです:
obclient> SELECT * FROM t1 outer apply (SELECT * FROM t2 WHERE t1.c1 = t2.c1 AND rownum <= 2) v;
+------+------+------+------+
| C1 | C2 | C1 | C2 |
+------+------+------+------+
| 1 | 10 | 1 | 100 |
| 1 | 10 | 1 | 101 |
| 2 | 20 | 2 | 200 |
| 3 | 30 | NULL | NULL |
+------+------+------+------+
右テーブルが関数式の場合、クエリ結果は次のとおりです:
-- ネストされたテーブル型を定義する
CREATE TYPE t2_c2_ntt AS TABLE OF NUMBER;
/
-- ネストされたテーブルを返す関数を定義する
CREATE OR REPLACE FUNCTION get_t2_c2(p_c1 INT)
RETURN t2_c2_ntt
IS
res t2_c2_ntt;
BEGIN
SELECT c2
BULK COLLECT INTO res
FROM t2
WHERE c1 = p_c1;
RETURN res;
END;
/
obclient> SELECT t1.c1, t1.c2, t2item.COLUMN_VALUE AS t2_c2 FROM t1 CROSS APPLY TABLE(get_t2_c2(t1.c1)) t2item;
+------+------+-------+
| C1 | C2 | T2_C2 |
+------+------+-------+
| 1 | 10 | 100 |
| 1 | 10 | 101 |
| 1 | 10 | 102 |
| 2 | 20 | 200 |
+------+------+-------+
右テーブルがコレクションコンストラクタの場合、クエリ結果は次のとおりです:
obclient> SELECT t1.c1, t1.c2, t2item.COLUMN_VALUE AS t2_c2
-> FROM t1
-> CROSS APPLY TABLE(
-> CAST(MULTISET(
-> SELECT c2 FROM t2 WHERE t2.c1 = t1.c1
-> ) AS t2_c2_ntt)
-> ) t2item;
+------+------+-------+
| C1 | C2 | T2_C2 |
+------+------+-------+
| 1 | 10 | 100 |
| 1 | 10 | 101 |
| 1 | 10 | 102 |
| 2 | 20 | 200 |
+------+------+-------+
右テーブルがJSONテーブルの場合、クエリ結果は次のとおりです:
obclient> CREATE TABLE t_json (
id NUMBER,
data CLOB -- JSON文字列を格納
);
obclient> INSERT INTO t_json VALUES (1, '{"items":[{"name":"A","val":10},{"name":"B","val":20}]}');
obclient> INSERT INTO t_json VALUES (2, '{"items":[{"name":"C","val":30}]}');
obclient> SELECT
-> t.id,
-> jt.name,
-> jt.val
-> FROM
-> t_json t
-> CROSS APPLY
-> JSON_TABLE(
-> t.data,
-> '$.items[*]'
-> COLUMNS (
-> name VARCHAR2(10) PATH '$.name',
-> val NUMBER PATH '$.val'
-> )
-> ) jt;
+------+------+------+
| ID | NAME | VAL |
+------+------+------+
| 1 | A | 10 |
| 1 | B | 20 |
| 2 | C | 30 |
+------+------+------+