FOREACH
関数は、セットのメンバーごとに計算を実行し、その結果をセットに集約します。
FOREACH
は、式を受け入れるEQL文内のコンテキストで使用できます: LET
、SELECT
、行関数またはアグリゲータ引数、WHERE
、HAVING
またはORDER BY
。 FOREACH
は常にセットに評価されるため、コンテキストはセット・タイプの式を受け入れる必要があります。そうしないと、EQLでチェック・エラーが発生します。
構文
FOREACH
関数の構文は、次のとおりです:
FOREACH id_1 IN set_1[, id_n IN set_n] RETURN(expression)説明:
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 SourceEQLでは、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はxとy (
FOREACH
RETURN
式内)をFOREACH
でバインドされた識別子への参照として解釈しますが、xとyは以前の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)ここで、最初の汎用は整数のセットであるため、xは
RETURN
式に整数のタイプを持っています。 同様に、2番目の汎用は文字列のセットであるため、yには型文字列があります。 その結果、RETURN
式x + yは不正タイプになる(それに応じてEQLによってエラーが発行される)ようになります。
RETURN
式にアトミック・タイプtが含まれる場合、FOREACH
式全体のタイプはtになります。 したがって、RETURN
式に型整数が指定されている場合、その式を構成するFOREACH
式には、型整数が設定されます。
一方、RETURN
式にセット・タイプがある場合、FOREACH
式はRETURN
式と同じタイプになります。 (これは、FOREACH
がRETURN
式の値を結合する場合に対応します。) そのため、RETURN
式で文字列のセットが生成される場合、FOREACH
式でも同じように処理されます。
FOREACHと集計
FOREACH
式は、グループ化前とグループ化後の両方の計算(WHERE
、HAVING
および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}の各メンバーに対してRETURN
式x * 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つのセットの値xとyのすべての組合せについて
RETURN
式x + 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
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})
// 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列内のすべてのセットのユニオンを計算すると、最終的な結果が得られます。
| 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の例
RETURN
式が各スコア・セットの値のみを返すため、FOREACH
式の最も単純な例の1つです:
RETURN Results AS SELECT WineID AS id, FOREACH x IN Score RETURN(x) AS ratings FROM WineState ORDER BY id
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
関数が使用されています。
LET
とFOREACH
の両方を使用し、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
RETURN
式内でのみ表示され、その式内で同じ名前を持つ他の属性の影が表示されます。 yearSetはSELECT
句ではなくLET
句で定義されるため、文の結果には表示されません。