MEMBERSはGROUP BYに対する1つの拡張であり、セットのメンバーによるグルーピングを使用できます。
MEMBERSを使用すると、複数割当て属性によりグルーピングできます。複数割当て属性によるグルーピングの際には、すべての行(属性に割当てがない行を含む)が保持されることに注意してください。
GROUP BY MEMBERS(<set>) AS <alias> [,MEMBERS(<set2>) AS <alias2>]*ここで、
LETが使用されていない場合、MEMBERSはソース文またはコレクションの属性のみ(つまり、ローカル定義ではない)を参照できます。LETが使用されている場合、MEMBERSで同じ文内で定義されている属性(属性がSELECT句ではなく、LET句で定義されている場合)を参照できます。
構文に示したように、EQLは同時に複数セットのメンバーによるグルーピングをサポートしています。これを行うには、複数のMEMBERS句を1つのGROUPリストに含めるだけです。
GROUP BY ROLLUP(a, b, MEMBERS(c) AS cValue, d)
セットのメンバーによるグルーピングは、1つのコレクションに対するものだけでなく任意の文で使用可能です(これは、EQLがセット内のすべての値を文境界を越えて保持するためです)。
Argument to MEMBERS has type mdex:double; only set types are permitted.
このエラーの例では、MEMBERSが複数割当てのdouble属性(mdex:double-set)ではなく、単一割当てのdouble属性(mdex:double)で使用されています。
RETURN Results AS SELECT SET(WineID) AS IDs FROM WineState GROUP BY MEMBERS(Body) AS bodyType
IDs bodyType ------------------------------------------------------- | { 14, 15 } | Supple | | { 22, 25 } | Firm | | { 19 } | Fresh | | { 11, 19, 22, 23, 24, 25, 4, 6, 8 } | Robust | | { 10, 11, 12, 13, 16, 18, 3, 4, 5, 7, 9 } | Tannins | | { 10, 12, 13, 16, 18, 3, 5, 7, 9 } | Silky | | { 1, 17, 2, 20, 21 } | | -------------------------------------------------------
結果を見ると、いくつかのレコードに2つのBodyが割り当てられているため、それらのレコードが複数のバケットの対象となっています。結果の最後の5つのレコードにはBody属性が割り当てられていませんが、グルーピング時に破棄されず、NULLのbodyTypeでリストされます。(WineIDを使用することで、IDセット内の値が表示され、どの入力行がどの出力行に含まれるかを確認できます。たとえば、レコード4はRobustとTanninsの両方に含まれ、レコード14はSuppleにのみ含まれます。レコード16はTanninsとSilkyに含まれます。)
RETURN Results AS SELECT SET(WineID) as IDs FROM WineState WHERE WineType = 'White' GROUP BY MEMBERS(Body) AS bodyType, MEMBERS(Score) AS scoreValue
IDs bodyType scoreValue ------------------------ | { 25 } | Firm | 82 | | { 25 } | Firm | 84 | | { 19 } | Fresh | 88 | | { 25 } | Robust | 82 | | { 25 } | Robust | 84 | | { 19 } | Robust | 88 | | { 20 } | | 71 | | { 20 } | | 75 | | { 21 } | | 87 | | { 21 } | | 89 | ------------------------
WineID=25であるレコードは、{Firm、Robust}と{82、84}のクロス積に対応して、4つのバケットの対象となっています。レコード20および21は、Score属性は割り当てられていますが、Body属性は割り当てられていないため、bodyTypeはNULLでscoreValueは各値でリストされています。
セット・メンバーによるグルーピングはGROUPING SETS (CUBE、ROLLUPを含む)と対話して、一見したところ予期していないような結果を生成する場合があることに注意してください。
RETURN Results AS SELECT SUM(Price) AS totalPrice FROM WineState GROUP BY ROLLUP(WineType)
WineType totalPrice ---------------------------- | Blanc de Noirs | 16.99 | | Brut | 46.98 | | Zinfandel | | | Merlot | 25.99 | | Bordeaux | 21.99 | | Chardonnay | 52.90 | | White | 97.97 | | Pinot Noir | 14.99 | | Red | 142.34 | | | 420.15 | ----------------------------
各WineType対して1行が割り当てられ、1番下にはサマリーを示す行があります。結果には、すべてのWineType値に対するレコードが含まれています。SUMは結合であるため、予期される動作は、totalPriceのサマリー行がその他すべての行のtotalPrice値の合計と等しくなることであり、実際に420.15は予期した結果に一致しています。(Whiteワインの合計は97.97です。)
RETURN Results AS SELECT SUM(Price) AS totalPrice FROM WineState WHERE WineType = 'White' GROUP BY ROLLUP(WineType, MEMBERS(Body) AS bodyType)
WineType bodyType totalPrice -------------------------- | White | Firm | 43.99 | | White | Fresh | 20.99 | | White | Robust | 64.98 | | White | | 32.99 | | White | | 97.97 | | | | 97.97 | --------------------------
この場合、サマリー行と個別の行の間の対応関係が予期した結果になっていません。'White'のサマリー行(つまり、WineTypeがWhiteでbodyTypeがNULLである行)のtotalPriceが、その行より上の(White、Firm)、(White、Fresh)および(White、Robust)の各行のtotalPriceの合計になると予期したはずです。
しかし、最初の4行の合計金額を加算すると、予期される値97.97ではなく、162.95になります。この相違が生じる理由は、セットのメンバーによるグルーピングを行った際に、1行が複数のバケットの対象となってしまったためです。特に、レコード19には2個のBody (FreshおよびRobust)が割り当てられているため、(White、Fresh)と(White、Robust)の両方の行の対象となってしまい、実際にその価格が二重に数えられています。
ただし、EQLがWineType (単一割当て属性)によるグルーピングを行って'White'のサマリー行を効率的に計算しているため、各入力行は正確に1度だけ数えられます。