MEMBERSはGROUP BYに対する1つの拡張であり、セットのメンバーによるグルーピングを使用できます。
MEMBERSを使用すると、複数割当て属性によりグルーピングできます。複数割当て属性によるグルーピングの際には、属性が割り当てられていない行はグルーピング時に破棄されることに注意してください。
GROUP BY MEMBERS(<set>) AS <alias> [,MEMBERS(<set2>) AS <alias2>]*ここで、
構文に示したように、EQLは同時に複数セットのメンバーによるグルーピングをサポートしています。これを行うには、複数のMEMBERS句を1つのGROUPリストに含めるだけです。
GROUP BY ROLLUP(a, b, MEMBERS(c) AS cValue, d)
コーパス間のメンバーだけではなく、セットのメンバーによるグルーピングも任意の文で使用可能です(これは、EQLがセット内の文境界にわたるすべての値を保存しているためです)。
Cannot apply MEMBERS to mdex:double. A set type is required
このエラーの例では、MEMBERSが複数割当てのdouble属性(mdex:double-set)ではなく、単一割当てのdouble属性(mdex:double)で使用されています。
RETURN results AS SELECT SET(WineID) AS IDs GROUP BY MEMBERS(Body) AS bodyType
IDs bodyType ------------------------------------------------------- | { 19 } | Fresh | | { 22, 25 } | Firm | | { 14, 15 } | Supple | | { 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 | -------------------------------------------------------
結果を見ると、いくつかのレコードに2つのBodyが割り当てられているため、それらのレコードが複数のバケットの対象となっています。また、5つのレコードにはBody属性が割り当てられていないため、バケットの対象とはならず、これらのレコードはグルーピング時に破棄されます。
RETURN results AS SELECT SET(WineID) as IDs WHERE WineType = 'White' GROUP BY MEMBERS(Body) AS bodyType, MEMBERS(Score) AS scoreValue
IDs bodyType scoreValue ------------------------ | { 19 } | Fresh | 88 | | { 25 } | Firm | 82 | | { 25 } | Firm | 84 | | { 25 } | Robust | 82 | | { 25 } | Robust | 84 | | { 19 } | Robust | 88 | ------------------------
WineID=25であるレコードは、{Firm、Robust}と{82、84}のクロス積に対応して、4つのバケットの対象となっています。
セット・メンバーによるグルーピングはGROUPING SETS (CUBE、ROLLUPを含む)と対話して、一見したところ予期していないような結果を生成する場合があることに注意してください。
RETURN results AS SELECT SUM(Price) AS totalPrice GROUP BY ROLLUP(WineType)
WineType totalPrice ---------------------------- | Pinot Noir | 14.99 | | White | 97.97 | | Blanc de Noirs | 16.99 | | Zinfandel | | | Brut | 46.98 | | Red | 142.34 | | Merlot | 25.99 | | Bordeaux | 21.99 | | Chardonnay | 52.90 | | | 420.15 | ----------------------------
各WineType対して1行が割り当てられ、1番下にはサマリーを示す行があります。結果には、すべてのWineType値に対するレコードが含まれています。SUMは結合であるため、予期される動作は、totalPriceのサマリー行がその他すべての行のtotalPrice値の合計と等しくなることであり、実際に420.15は予期した結果に一致しています。(Whiteワインの合計は97.97です。)
RETURN results AS SELECT SUM(Price) AS totalPrice WHERE WineType = 'White' GROUP BY ROLLUP(WineType, MEMBERS(Body) AS bodyType)
WineType bodyType totalPrice -------------------------- | White | Fresh | 20.99 | | White | Firm | 43.99 | | White | Robust | 64.98 | | White | | 97.97 | | | | 97.97 | --------------------------
この場合、サマリー行と個別の行の間の対応関係が予期した結果になっていません。'White'のサマリー行(つまり、WineTypeがWhiteでbodyTypeがNULLである行)のtotalPriceが、その行より上の(White、Firm)、(White、Fresh)および(White、Robust)の各行のtotalPriceの合計になると予期したはずです。
ただし、最初の3行のtotalPriceを加算すると、予期される値97.97ではなく、129.96が得られます。この相違が生じる理由は、セットのメンバーによるグルーピングを行った際に、1行が複数のバケットの対象となってしまったためです。特に、レコード19には2個のBody (FreshおよびRobust)が割り当てられているため、(White、Fresh)と(White、Robust)の両方の行の対象となってしまい、実際にその価格が二重に数えられています。同様に、レコード20にはBodyが割り当てられていないため、bodyTypeがNULLではないいずれのバケットの対象ともなっていません。これは、Bodyの値が空のセットであるためです。
ただし、EQLがWineType (単一割当て属性)によるグルーピングを行って'White'のサマリー行を効率的に計算しているため、各入力行は正確に1度だけ数えられます。