30.9 複数値関数ベースの索引の使用
WHERE
句のjson_exists
問合せでは、対象とするデータが索引に指定されたスカラー型と一致する場合(かつその場合にかぎり)、複数値関数ベースの索引を選択できます。
SQL/JSON条件json_exists
の複数値関数ベースの索引は、個別にまたはJSON配列の要素としてスカラーJSON値を対象とします。複数値索引は、JSON
データ型として格納されているJSONデータに対してのみ定義できます。
条件json_exists
は、対象となるデータが問合せのSQL/JSONパス式(または同等の単純なドット表記法構文)と一致する場合にtrueを返します。それ以外の場合、falseを返します。通常は、パス式にフィルタ式を含めます。つまり、照合では対象データがフィルタを満たす必要があります。
名前に"only"を含むデータ型変換項目メソッド(numberOnly()
など)を使用して定義される複数値索引は、同様に同じ項目メソッドを使用するjson_exists
問合せによってのみ選択できます。つまり、問合せでは同じ項目メソッドを明示的に使用する必要があります。詳細は、JSON_EXISTSの複数値関数ベースの索引の作成を参照してください。
項目メソッドを使用せずに、または名前に"only"が含まれていないデータ型変換項目メソッド(number()
など)を使用して定義された複数値索引は、項目メソッドで指定された型に変換できるスカラー値を(おそらく配列要素として)対象とする問合せで選択できます。データ型変換項目メソッドの詳細は、SQL/JSONパス式の項目メソッドを参照してください。
この例では、WHERE
句でSQL/JSON条件json_exists
を使用して、730
に一致するsubparts
フィールド値がないかチェックします。これらは、複数値索引mvi
、cmvi_1
およびcmvi_2
(JSON_EXISTSの複数値関数ベースの索引の作成で定義)を選択できるどうかの観点で説明されています。JSONスカラー値のSQLスカラー値への変換は、表18-2を参照してください。
例30-17 項目メソッドnumberOnly()を使用したJSON_EXISTS問合せ
この例では、WHERE
句で項目メソッドnumberOnly()
を使用します。パス式が数値のsubparts
値730
(たとえばsubparts : 730
)または1つ以上の数値の要素730
が含まれる配列のsubparts
値(たとえばsubparts:[630, 730, 690, 730]
)を対象とする場合、問合せでは索引mvi
を選択できます。対象となる文字列値"730"
(たとえばsubparts:"730"
またはsubparts:["630", "730", 690, "730"]
)に対しては、索引mvi
を選択できません。
かわりに、項目メソッドnumber()
を使用して索引mvi
が定義されている場合、この問合せでは、数値のsubparts
値730
、文字列のsubparts
値"730"
または数値要素730
または文字列要素"730"
が含まれる配列のsubparts
値に対して索引を選択できます。
SELECT count(*) FROM parts_tab
WHERE json_exists(jparts, '$.parts.subparts?(@.numberOnly() == 730)');
例30-18 項目メソッドnumberOnly()を使用しないJSON_EXISTS問合せ
これらの2つの問合せでは、項目メソッドnumberOnly()
を使用しません。1つ目はメソッドnumber()
を使用します。このメソッドは対象データを数値に変換します(可能な場合)。2つ目は対象データを型変換しません。
索引mvi
は、対象データが数値730
であっても、どちらの問合せでも選択できません。索引はnumberOnly()
を使用して定義されているため、索引を選択するには、問合せでnumberOnly()
を使用する必要があります。
SELECT count(*) FROM parts_tab t
WHERE json_exists(jparts, '$.parts.subparts?(@.number() == 730)');
SELECT count(*) FROM parts_tab t
WHERE json_exists(jparts, '$.parts.subparts?(@ == 730)');
例30-19 複数フィールドをチェックするJSON_EXISTS問合せ
この問合せのフィルタ式では、SQL NUMBER
値4
と一致するpartno
フィールド(おそらくJSON文字列からの変換によるもの)および数値730
と一致するフィールドsubparts
の有無を指定します。
この問合せでは、索引cmvi_1
またはcmvi_2
のいずれかを選択できます。各行に数値4
と一致するparts.partno
値と、数値730
と一致するparts.subparts
値があるため、データのどちらの行もこれらの索引と一致します。subparts
一致の場合、1行目にはsubparts
値730
が、2行目には値730
が含まれる配列であるsubparts
値があります。
SELECT a FROM parts_tab
WHERE json_exists(jparts,'$.parts[*]?(@.partno == 4 &&
@.subparts == 730)');
例30-20 配列要素の位置をチェックするJSON_EXISTS問合せ
この例は例30-19に似ていますが、フィールドpartno
が数値4
と一致する必要があることに加えて、ここでのフィルタ式では、フィールドsubparts
の値が少なくとも2つの要素の配列と一致し、配列の2つ目の要素が数値730
と一致している必要があります。
この問合せでは、位置述語[1]
に対しても含め、索引cmvi_2
を選択できます。索引cmvi_2
では、仮想列subpartNum
を指定します。これは、最終列FOR ORDINALITY
の直前、最後から2番目の列としてJSONフィールドsubparts
に対応します。
この問合せでは索引cmvi_1
も選択できますが、その索引にFOR ORDINALITY
列がないため、使用するには、配列の位置条件[1]
を評価するために追加ステップが必要になります。索引cmvi_2
の使用には、このような追加ステップは必要ないため、このような問合せのパフォーマンスは向上します。
SELECT a FROM parts_tab
WHERE json_exists(jparts,'$.parts[*]?(@.partno == 4 &&
@.subparts[1] == 730)');