プライマリ・コンテンツに移動
Oracle® Big Data Discovery Cloud Service EQLリファレンス

E65371-04
目次へ
目次
索引へ移動
索引

前
次
機械翻訳について

FOREACH関数

FOREACH関数は、セットのメンバーごとに計算を実行し、その結果をセットに集約します。

FOREACHは、式を受け入れるEQL文内のコンテキストで使用できます: LETSELECT、行関数またはアグリゲータ引数、WHEREHAVINGまたはORDER BY FOREACHは常にセットに評価されるため、コンテキストはセット・タイプの式を受け入れる必要があります。そうしないと、EQLでチェック・エラーが発生します。

構文

FOREACH関数の構文は、次のとおりです:
FOREACH id_1 IN set_1[, id_n IN set_n] RETURN(expression)
説明:
  • idは、計算するアイテムの任意の識別子です。 識別子にはNCName形式を使用する必要があります。
  • setは、任意のセット・データ型のセットです。
  • expressionはEQL式です。 式はカッコで囲み、RETURNキーワードが必須です。 idパラメータの数に関係なく、関数にはRETURNを1つのみ含める必要があります。

少なくとも1つの識別子/セット・ペア(id IN set)とRETURN式を指定する必要があります。

スコープとシャドウ

FOREACHでは、RETURN式内でid_n識別子を使用してid_1がバインドされます。set_1からset_nまでの範囲ではありません。 これらのバインディングにより、FOREACH関数のポイントでスコープ内に存在する可能性のあるid_nを通じて、id_1のその他のバインドがシャドウ化されます。

EVERYおよびSOMEの数量詞と同様に、EQLでは、バインドされた変数への参照をデータソースの別名で修飾することはできません。 たとえば、次の文を考えてみます:
RETURN results AS
  SELECT
    Source.x AS x,
    FOREACH x IN {1, 2}, y in {3, 4} RETURN (results.x + Source.y) AS vals
  FROM Source
EQLでは、results.xへの参照が(FOREACH RETURN式で) SELECT句によって定義されたxへの参照として(つまり、Source.xの別名として、FOREACHによりバインドされたxへの参照としてではありません)解釈されます。 同様に、EQLでは参照Source.y「ソース」の属性yへの参照として解釈されます。
ただし、文修飾子を削除する場合は、次のようになります:
RETURN results AS
  SELECT
    Source.x AS x,
    FOREACH x IN {1, 2}, y in {3, 4} RETURN (x + y) AS vals
  FROM Source
その後、EQLはxy (FOREACH RETURN式内)をFOREACHでバインドされた識別子への参照として解釈しますが、xyは以前のSELECTからのスコープですでに存在します。 したがって、「値」では常に値 {4, 5, 6}が設定されます。

タイプ

FOREACH構文では、set_1 through set_nはsetデータ型(mdex:string-setなど)である必要があります。EQLはエラーを通知します。それ以外の場合はエラーを発行します。 対応するx_1からx_nへの識別子は、これらのセットの要素のタイプを持つ必要があります。 例として、次の例を考えてみます:
FOREACH x IN {1, 2}, y IN {'abc', 'def'} RETURN (x + y)
ここで、最初の汎用は整数のセットであるため、xRETURN式に整数のタイプを持っています。 同様に、2番目の汎用は文字列のセットであるため、yには型文字列があります。 その結果、RETURNx + yは不正タイプになる(それに応じてEQLによってエラーが発行される)ようになります。

RETURN式にアトミック・タイプtが含まれる場合、FOREACH式全体のタイプはtになります。 したがって、RETURN式に型整数が指定されている場合、その式を構成するFOREACH式には、型整数が設定されます。

一方、RETURN式にセット・タイプがある場合、FOREACH式はRETURN式と同じタイプになります。 (これは、FOREACHRETURN式の値を結合する場合に対応します。) そのため、RETURN式で文字列のセットが生成される場合、FOREACH式でも同じように処理されます。

FOREACHと集計

FOREACH式は、グループ化前とグループ化後の両方の計算(WHEREHAVINGおよびORDER BYの各句を含む)に表示できます。 次に、数量式(EVERYおよびSOME)が行うのとほとんど同じ方法で集計と対話します:
  • FOREACH式は、アグリゲータ引数内に表示できます:
    RETURN results AS
      SELECT
        SET_UNIONS(FOREACH x IN e RETURN(b)) AS unions
      FROM Source
      GROUP
  • アグリゲータは、FOREACHとそのバウンド変数の間に表示できません。 つまり、次のものは無効であり、EQLによってエラーが通知されます:
    FOREACH x IN e RETURN(SUM(x))

操作の詳細

FOREACHの動作を説明するために、簡単な例を使用します:
FOREACH x IN {1, 2, 3} RETURN(x * 2 + 1)

この式はセット {3, 5, 7}として評価されます。 これは、暗黙的に、EQLはセット {1, 2, 3}の各メンバーに対してRETURNx * 2 + 1を1回評価し、xでそのセットの各要素を順番に取得するためです。 最後に、EQLはこれらの評価の結果を別のセットにアセンブルします。

汎用性と結果はどちらもセットであるため、トラバースが汎用の要素を訪問する順序、または最終セットに結果値が出現する順序は指定できません。

FOREACHを使用して、複数セットを反復処理することもできます:
FOREACH x IN {1, 2, 3}, y IN {40, 50, 60} RETURN(x + y)
この式は、セット {41, 42, 43, 51, 52, 53, 61, 62, 63}に評価されます。 ここで、EQLは2つのセットの値xyのすべての組合せについてRETURNx + yを評価します:
x = 1, y = 40: x + y = 41
x = 2, y = 40: x + y = 42
x = 3, y = 40: x + y = 43
x = 1, y = 50: x + y = 51
...
x = 3, y = 60: x + y = 63
セットには重複する値やNULLを含めることができないため、次の2つの例に示すように、FOREACH式の結果が重複(または汎用のクロス積)より小さくなる場合があります:
FOREACH x IN {-1, 1, 2}      RETURN (ABS(x))        // returns {1, 2}
FOREACH x IN {'3', '4', 'y'} RETURN (TO_STRING(x)) // returns {3, 4}
最初の例では、ABS(-1) = ABS(1) = 1,であるため、最後のセットには2つの要素のみが含まれます。値1は2回出現しない場合があります。 2番目の例では、TO_INTEGER('x')がNULLであるため、この値は最後のセットには出現しません。
RETURN式自体で(単一の値ではなく)セットが生成される場合、FOREACHは前述のように評価しますが、すべてのRETURNセットの結合を最終結果として計算します。 次に例を示します。
FOREACH x in {3, 4, 5}, y IN {-1, 0, 2} RETURN ({x + y, x - y})
セット {1, 2, 3, 4, 5, 6, 7}は次のように評価されます:
// Note: "body" is the RETURN expression
| x | y  | body  |
------------------
| 3 | -1 | {2,4} |
| 3 |  0 | {3}   |
| 3 |  2 | {1,5} |
| 4 | -1 | {3,5} |
| 4 |  0 | {4}   |
| 4 |  2 | {2,6} |
| 5 | -1 | {4,6} |
| 5 |  0 | {5}   |
| 5 |  2 | {3,7} |
------------------

body列内のすべてのセットのユニオンを計算すると、最終的な結果が得られます。

前述の説明の重要な結果は、汎用セットが空の場合に、結果セット自体が空であるということです。 たとえば、割当て値が次の2つの複数割当て属性があるとします:
| xs    | ys    |
-----------------
| {1,2} | {3}   |
| {}    | {4,5} |
| {6}   | {}    |
-----------------
その後、次の文があります:
RETURN results AS
  SELECT
    xs,
    ys,
    FOREACH x IN xs, y IN ys RETURN (x + y) AS zs
  FROM InputState
は、次の結果が生成されます:
| xs    | ys    | zs    |
-------------------------
| {1,2} | {3}   | {4,5} |
| {}    | {4,5} | {}    |
| {6}   | {}    | {}    |
-------------------------

FOREACHの例

例1: これは、複数割当の整数属性(スコア)が1つのみ使用され、RETURN式が各スコア・セットの値のみを返すため、FOREACH式の最も単純な例の1つです:
RETURN Results AS
SELECT
   WineID AS id,
   FOREACH x IN Score RETURN(x) AS ratings
FROM WineState
ORDER BY id
例2: この例では、2つの複数割当て文字列属性(BodyとFlavors)を使用し、セットのメンバーを連結しています:
RETURN Results AS
SELECT
   WineID AS id,
   FOREACH x IN Body, y IN Flavors RETURN (CONCAT(x, ' ', y)) AS bodyflavor
FROM WineState
WHERE IS_NOT_EMPTY(Body) AND IS_NOT_EMPTY(Flavors)
ORDER BY id

空のセットが選択されないように、WHERE句では2つのIS_NOT_EMPTY関数が使用されています。

例3: この例では、LETFOREACHの両方を使用し、RETURN式では、EXTRACT関数も使用しています:
RETURN Results AS
LET 
   (FOREACH d IN ShipDate RETURN (EXTRACT(d, YEAR))) AS yearSet
SELECT
   SET(Price) AS prices
FROM WineState
GROUP BY MEMBERS(yearSet) AS shipyear
この例では、ShipDateは複数割当のdateTime属性です。 d属性はRETURN式内でのみ表示され、その式内で同じ名前を持つ他の属性の影が表示されます。 yearSetSELECT句ではなくLET句で定義されるため、文の結果には表示されません。