本文へスキップ
`Ctrl`+`K`

# 7.16.1. `between`

## 7.16.1.1. 概要

`between` は、指定された値が指定された範囲にあるかをチェックするために使われます。これは select の filter オプションと組み合わせてよく使われます。

## 7.16.1.2. 構文

`between` は3つから6つの引数を受け取ります。

    between(column_or_value, min, max)
    between(column_or_value, min, max, {"option": "value of option"})
    between(column_or_value, min, min_border, max, max_border)
    between(column_or_value, min, min_border, max, max_border, {"option": "value of option"})

## 7.16.1.3. 使い方

使い方を示すために使うスキーマ定義とサンプルデータは以下の通りです。

実行例:

    table_create Users TABLE_HASH_KEY ShortText
    # [[0,1337566253.89858,0.000355720520019531],true]
    column_create Users age COLUMN_SCALAR Int32
    # [[0,1337566253.89858,0.000355720520019531],true]
    table_create Ages TABLE_HASH_KEY Int32
    # [[0,1337566253.89858,0.000355720520019531],true]
    column_create Ages user_age COLUMN_INDEX Users age
    # [[0,1337566253.89858,0.000355720520019531],true]
    load --table Users
    [
    {"_key": "Alice",  "age": 12},
    {"_key": "Bob",    "age": 13},
    {"_key": "Calros", "age": 15},
    {"_key": "Dave",   "age": 16},
    {"_key": "Eric",   "age": 20},
    {"_key": "Frank",  "age": 21}
    ]
    # [[0,1337566253.89858,0.000355720520019531],6]

これはPG-13 (MPAA)のレーティングに該当する人を示すクエリです。

実行例:

    select Users --filter 'between(age, 13, "include", 16, "include")'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "age",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         2,
    #         "Bob",
    #         13
    #       ],
    #       [
    #         3,
    #         "Calros",
    #         15
    #       ],
    #       [
    #         4,
    #         "Dave",
    #         16
    #       ]
    #     ]
    #   ]
    # ]

13から16歳までのユーザーを返します。

`between` 関数はテーブルのカラムだけでなく、値も受け付けます。

最初の引数に値を指定した場合、その値が含まれているか否かをチェックします。もし、指定した範囲にマッチしたら、( `between` 関数がtrueを返すので)すべてのレコードを返します。もし、指定した範囲にマッチしなかった場合、( `between` 関数がfalseを返すので)1件もレコードを返しません。

実行例:

    select Users --filter 'between(14, 13, "include", 16, "include")'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         6
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "age",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         1,
    #         "Alice",
    #         12
    #       ],
    #       [
    #         2,
    #         "Bob",
    #         13
    #       ],
    #       [
    #         3,
    #         "Calros",
    #         15
    #       ],
    #       [
    #         4,
    #         "Dave",
    #         16
    #       ],
    #       [
    #         5,
    #         "Eric",
    #         20
    #       ],
    #       [
    #         6,
    #         "Frank",
    #         21
    #       ]
    #     ]
    #   ]
    # ]

上記の例では、すべてのレコードを返します。これは、14は指定した範囲である13から16の間にあるからです。この振舞いは指定した値がテーブルに存在するかどうかの確認に使えます。

Added in version 16.0.6: `between` は最初の引数としてベクターも受け付けます。

ベクターはシーケンシャルサーチでのみサポートしています。 `between` はまだベクターの値に対してインデックスを使いません。

最初の引数には、 `COLUMN_VECTOR` カラムやベクターリテラルなどのベクターの値を指定できます。この場合、 `between` はいずれかの要素が指定した範囲に含まれていればtrueを返します。そのため、 `between` を使って、範囲内に少なくとも1つの値を持つレコードを検索できます。

以下の例では `COLUMN_VECTOR` カラムを使います。各レコードは複数の価格を持ちます。 `between` は、 `[18, 20)` の範囲に少なくとも1つの価格が含まれるレコードを選択します。

実行例:

    table_create Products TABLE_HASH_KEY ShortText
    # [[0,1337566253.89858,0.000355720520019531],true]
    column_create Products prices COLUMN_VECTOR Int32
    # [[0,1337566253.89858,0.000355720520019531],true]
    load --table Products
    [
    {"_key": "A", "prices": [17, 170, 1700]},
    {"_key": "B", "prices": [18, 180, 1800]},
    {"_key": "C", "prices": [19, 190]},
    {"_key": "D", "prices": [20]},
    {"_key": "E", "prices": [21, 210, 2100]}
    ]
    # [[0,1337566253.89858,0.000355720520019531],5]
    select Products --filter 'between(prices, 18, "include", 20, "exclude")'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "prices",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         2,
    #         "B",
    #         [
    #           18,
    #           180,
    #           1800
    #         ]
    #       ],
    #       [
    #         3,
    #         "C",
    #         [
    #           19,
    #           190
    #         ]
    #       ]
    #     ]
    #   ]
    # ]

`A` と `E` は、どの価格も範囲内にないため除外されます。 `D` は、 `20` が `"exclude"` によって除外されるため除外されます。 `B` と `C` は、それぞれ範囲内に少なくとも1つの価格を持つため選択されます。

ベクターの要素が異なる型を使っている場合、最初の要素の型が対象の型として使われ、他の型を使っている要素は無視されます。例えば、 `[180.0, 18]` では、最初の要素 `180.0` が浮動小数点数で `18` はそうではないため、 `18` は無視されます。

また、 `between` はオプションも指定できます。現在は、 `too_many_index_match_ratio` のみ指定できます。この値は、 `double` 型です。

`too_many_index_match_ratio` を使って、 `GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO` の値を変更できます。`GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO` のデフォルト値は `0.01` です。`GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO` は、 `between` がインデックスを使うかどうかを決定するために使います。

`between` とANDで絞り込むと予想されるレコード数よりも、絞り込んだレコード数が十分に小さい場合は、インデックスを使った検索より、シーケンシャルサーチの方が速いことがあります。

例えば、 `--filter` でレコードを絞り込んだあと、さらに `between` で絞り込むとします。

デフォルトでは、以下のケースでは、 `between` はシーケンシャルサーチを使います。

> 1. `--filter` で絞り込んだレコード数が1000で `between` 対象のレコード数が500,000の場合。

>        1,000/500,000 = 0.002 < 0.01(GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO) -> between use sequential search.

一方、以下のケースでは、 `between` はインデックスを使います。

> 2. `--filter` で絞り込んだレコード数が1000で `between` 対象のレコード数が50,000の場合。

>        1,000/50,000 = 0.02 > 0.01(GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO) -> between use index.

`between` のオプションを設定するクエリーは以下の通りです。:

実行例:

    select Users --filter 'between(age, 13, "include", 16, "include", {"too_many_index_match_ratio":0.001})'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "age",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         2,
    #         "Bob",
    #         13
    #       ],
    #       [
    #         3,
    #         "Calros",
    #         15
    #       ],
    #       [
    #         4,
    #         "Dave",
    #         16
    #       ]
    #     ]
    #   ]
    # ]

## 7.16.1.4. 引数

### 7.16.1.4.1. 必須引数

必須引数は3つあります。 `column_or_value` と `min` と `max` です。

#### 7.16.1.4.1.1. `column_or_value`

カラムもしくは値を指定します。

Added in version 16.0.6: ベクターもシーケンシャルサーチでのみ受け付けます。 `between` はいずれかの要素が指定した範囲に含まれていればtrueを返します。詳細は 使い方 を参照してください。

#### 7.16.1.4.1.2. `min`

範囲のうち最小値を指定します。デフォルトでは `min` を範囲に含めますが、 `min_border` 引数で含めるかどうかを制御できます。

#### 7.16.1.4.1.3. `max`

範囲のうち最大値を指定します。デフォルトでは値 `max` を範囲に含めますが、 `max_border` 引数で含めるかどうかを制御できます。

### 7.16.1.4.2. 省略可能引数

省略可能引数は2つあります。 `min_border` と `max_border` です。

#### 7.16.1.4.2.1. `min_border`

`min` の値を含めた範囲となるかどうかを指定します。 `min_border` に指定できるのは "include" または "exclude" のどちらかです。 "include" を指定すれば、`min` が含まれます。 "exclude" を指定すれば `min` は含まれません。

#### 7.16.1.4.2.2. `max_border`

`man` の値を含めた範囲となるかどうかを指定します。 `max_border` に指定できるのは "include" または "exclude" のどちらかです。 "include" を指定すれば、`max` が含まれます。 "exclude" を指定すれば `max` は含まれません。

#### 7.16.1.4.2.3. `{"option": "value of option"}`

`between` のオプションを指定します。現在は、 `too_many_index_match_ratio` のみ指定できます。この値は、 `double` 型です。

#### 7.16.1.4.2.4. 戻り値

`between` は指定した範囲にカラムの値が含まれるかを返します。もし該当するレコードがあれば、 `true` を返します。そうでなければ `false` を返します。