Microsoft SQL Server 2005 Beta 2 の MDX スクリプトの紹介
Richard Tkachuk
Microsoft Corporation
July 2004
適用対象:
Microsoft SQL Server 2005
MDX Scripting
要旨: この資料では、Microsoft SQL Server 2005 Beta 2 のマルチディメンション式 (MDX) を一般的なビジネスの問題に適用する方法について説明します。この資料では、MDX の詳しい知識があることを前提としています。
目次
はじめに
MDX の概念
MDX スクリプト
キューブの集計方法
Beta 2 で発生する可能性がある問題
はじめに
分析サービスでは、計算エンジンに基づく強力なサーバーが提供されます。これは、実際に多様な要求に応える大規模な表計算ソフトウェアです。この資料では、Microsoft SQL Server 2005 Beta 2 のマルチディメンション式 (MDX) を一般的なビジネスの問題に適用する方法について説明します。
この資料では、MDX の詳しい知識があることを前提としています。
MDX の概念
ここでは、いくつかの基本概念を紹介します。以下のセクションでは、スクリプトについて詳しく説明します。
キューブの領域
Microsoft SQL Server 2000 から大幅に発展したのは、属性の概念です。ディメンションにとっての属性は、リレーショナル データベース内のテーブルにとっての列と同じ関係にあります。たとえば、Customer ディメンションには、Name、Phone Number、Gender、City、State などの属性を含めることができます。
属性は、属性の階層でユーザーに公開されます。ディメンション内の属性の階層には、省略可能な All レベル、および属性の個々のメンバが含まれています。たとえば、Customer ディメンションには、2 つのレベルを持つ Name 属性の階層が含まれているとします。この 2 つのレベルとは、All レベル、および各名前のメンバを含む第 2 レベルです (親子階層は別に処理されます)。
キューブの領域を定義するのは、属性の階層です。ユーザーは、その属性の階層の結果として作成された多次元の領域としてキューブを考えることができます。ディメンションは、属性の階層のコンテナです。また、ディメンションには、ナビゲーションの便宜上、ユーザーの階層を含めることもできます。ただし、ユーザーの階層は、キューブの領域に影響しません。
属性には、属性の階層は必要ありません。属性の階層が作成されない場合、キューブの領域は属性と関係ありません。たとえば、一般的に、属性の階層は Phone Number 属性には作成されません。これは、通常、電話番号でディメンションをナビゲートできるようにする必要があまりないからです。属性の階層が属性に作成されない場合、属性をメンバ プロパティとして使用できますが、ユーザーの階層のレベルとしては使用できません。
ナビゲーションの不変性
セルの値は、その属性の階層の座標およびパスで完全に定義されています。セルの値は、ナビゲーション パス、またはユーザーの階層の有無に応じて変化しません。
たとえば、Geography というユーザーの階層 (Customer.Geography.USA.WA.Redmond.Richard) で定義されたセルは、属性の階層 (Customer.Country.USA、Customer.State.WA、Customer.City.Redmond、Customer.Name.Richard) で定義されたセルと同一です。
座標のセル (Customer.Name.Richard) は、(Customer.Geography.USA.WA.Redmond.Richard) と同じ座標ではありません。この原因は、ある属性の階層の 1 つのメンバが属性の階層の複数のメンバを暗に意味しないことにあります。つまり、(Customer.Name.Richard) が (Customer.Name.Richard, Customer.Country.All, Customer.State.All, Customer.City.All) と同じであることが原因です。顧客 Richard が米国ワシントン州のレドモンドに住んでいる場合であっても、Customer.Name.Richard という座標は、City、State、または Country 属性の階層の座標を意味しません。
ディメンションのリーフ
ディメンションにはリーフがあります。リーフの意味は、"粒度" 属性に基づいています。粒度属性は、ディメンションをメジャー グループにバインドする属性です。多くの場合、これはディメンション キーですが、必ずしもそうとは限りません。たとえば、Time ディメンションが Date 別にメジャー グループに関連付けられる場合、Time ディメンションにより細かい詳細 (たとえば、分単位まで) が含まれていても、Date は粒度属性です。
リーフは、ファクト テーブルのデータが直接関連付けられているディメンションの座標です。さらに正確には、リーフは、属性の階層からのメンバの組み合わせで定義されます (このメンバの属性は、粒度属性に直接または間接的に関連しています)。この場合、メンバは All メンバではありません。たとえば、Name (粒度属性)、Email、City、State、および Country という属性を含む Customer ディメンションでは、次のディメンションの座標がリーフです。
(Customer.Name.Name.Richard, Customer.Email.Email.richard@Adventureworks.com, Customer.City.City.Sammamish, Customer.State.State.WA, Customer.Country.Country.USA)
ただし、次のディメンションの座標はリーフではありません。これは、Email 属性の階層からのメンバが All レベルであるためです。
(Customer.Name.Name.Richard, Customer.Email.[(All)].[All], Customer.City.City.Sammamish, Customer.State.State.Wa, Customer.Country.Country.USA)
粒度属性がディメンションの主要な属性ではない場合、リーフには、粒度属性に関連しない属性の All メンバが含まれます。たとえば、Customer ディメンションの粒度属性が City 属性の場合、次のディメンションの座標はリーフです。
(Customer.Name.[(All)].[All], Customer.Email.[(All)].[All], Customer.City.City.Sammamish, Customer.State.State.Wa, Customer.Country.Country.USA)
注 粒度属性に関連しない属性のメンバと交差するセルには、データが存在しない可能性があります。たとえば、粒度属性が City の場合、Name 属性のメンバでのスライシングにより、空のセルが生成されます。正確な動作は、メジャー グループの IgnoreUnrelatedDimensions プロパティで決まります。
定義によると、粒度属性のメンバごとに 1 つのリーフがあります。
Autoexists
実際のキューブの領域は、そのキューブの属性の階層の結果としての領域よりも制限されています。同じディメンションの互いに共存しない Autoexists 属性のメンバがこのキューブの領域に存在しないことが原因で存在しないセルがあります。たとえば、(Beijing, Canada) は存在しません。Autoexists の概念は、このドキュメント全体で使用されています。
注 これは、ファクト テーブルのデータとは関係ありません。Autoexists は単なるディメンションの概念です。Autoexists は、同じディメンション内の属性のみに関係があります。
クエリは、キューブの領域内に存在しないセルを要求することがあります。たとえば、select customer.gender.members on 0, {Customer.Name.Fred, Customer.Name.Jane} on 1 from sales というステートメントには、この領域に存在しないセルが含まれています。このようなセルは、常に空を返します。セルには、計算を含めたり、書き込みを行うことができません。
Autoexists は、クエリの結果で大きな役割を担っています。
一般的なディメンションの性質を持つセットを同じ軸に従って計画すると、共存するメンバが保持されます。
以下に例を示します。
Select crossjoin({Customer.Country.Country.USA}, Customer.States.States.members) on 0 from Sales
結果 : USA にある州のみが Customer.States.States.members から保持されます。
全階層のすべてのメンバは、同じディメンション内のすべての階層のその他のすべてのメンバと自動的に存在します。
サブキューブ
サブキューブは、後に続くステートメント用の領域をサブ領域に制限するクロス結合のセットのコレクションです。サブキューブは頻繁に参照されるため、有効なサブキューブの形式には制限があります。サブキューブの定義の各セットは、以下のようになります。
All メンバを除いた、属性の階層からのメンバの任意のコレクション。
単一のメンバに解決する階層または MDX 式の単一のメンバ。
自然階層で指定したレベルのメンバの任意のコレクション (親子階層は除きます。これは Beta 2 の制約です)。
注 自然階層は、属性で構成されています。この場合、各属性は、以下の属性のメンバ プロパティです。たとえば、City が Name のメンバ プロパティ、State が City のメンバ プロパティ、および Country が State のメンバ プロパティの場合、Geography 階層の Country、State、City、および Name は自然階層です。Gender-Age 階層は、Gender が Age のメンバ プロパティではないため、自然階層ではありません。
複数レベルでのメンバの子孫 (自然階層の場合のみ)。Bata 2 では、親子階層は除外されています。
階層のすべてのメンバ。
階層のリーフ メンバ。
引数 "*" は、サブキューブの定義で使用できます。これは、キューブのコンテンツ全体 (すべてのディメンションからのすべての階層の全メンバ) を表します。
軸の階層性
同じ階層のメンバをクエリ内のさまざまな軸で計画する方法のルールがあります。
共通する次元を持つが、任意の軸に沿って異なる階層性を持つセットを計画する場合、制限事項はありません。
同じ階層性を持つセットを、複数の軸に含めることができません。
注 オブジェクトの階層性は、オブジェクトに存在する階層を表します。
上位について
SQL Server 2000 分析サービスでは、データはレベルごとに集計されました。たとえば、Customer ディメンションでは、Country、State、City、および Name のデータが、Name から City、State、Country の順番に集計されました。計算によって、たとえば Redmond の値 (ただし、個別の顧客の値ではありません) が変更された場合、Redmond より上位の値では変更が反映されました。つまり、Washington、USA、および All Customer メンバの値は影響を受けました。
SQL Server 2005 のデータの集計方法は似ていますが、属性の階層以外の階層がキューブに含まれない可能性があるため、少し異なります。言い換えると、階層で "上位" が何を意味するかが定義されていない場合、どのようにデータを "上位に" 集計するのでしょうか? Customer ディメンションに多数の属性が含まれ、ユーザー定義の階層が含まれていない場合、何をどこから集計しますか ?
この質問には、属性の "粒度" を使用してキューブの領域を再調査すると、答えることができます。キューブ内の各セルには、属性の階層に関する粒度が設定されています。そのため、セルは属性の All レベルまたは属性レベルのいずれかにあります (親子階層では、事態は多少複雑になりますが、原理は同じです)。属性の階層の All レベルには、属性の階層のレベルよりも高い粒度が設定されています。たとえば、Customer.City.[All] メンバは、Customer.City.Seattle よりも粒度が高くなっています。
各セルに粒度が設定されていることがわかると、粒度を使用して、上位の意味を定義できます。
1 つのセルですべての属性に同じ粒度が設定されている場合、そのセルは別のセルと同じ粒度です。
少なくとも 1 つの属性により高い粒度が設定され、他の属性がそれと同じかそれより高い粒度の場合、1 つのセルには別のセルより高い粒度が設定されます。
高度な注意 他のセルよりも上または下にあるセルは、比較可能とされています。上でも下でもないセルは、比較できないとされています。つまり、ある属性にはより高い粒度が設定され、別の属性にはより低い粒度が設定されている場合は、セルを比較できません。たとえば、組で定義されたセル (Customer.City.[All], Customer.Customer.Richard) は、セル (Customer.City.Sammamish, Customer.Customer.[All]) と比較できません。これは、ある属性が高く、別の属性が低いことが原因です。
方向性がわかったため、データを粒度の低い方から高い方へ集計するという、データの集計方法を定義できます。
これは役に立ちますが、完全な方法ではありません。キューブの中に計算を格納すると、キューブの集計方法、単項演算子、パスにどのように影響するでしょうか ? これは、以下のセクションで定義します。
MDX スクリプト
MDX スクリプトは、コマンドの集合です。各コマンドは、セミコロンで区切られています。スクリプトは、キューブに計算を設定する場合に使用されます。
ここでは、一般的な計算に役立つ MDX スクリプトおよびいくつかの新しい関数の主な概念について説明します。
実行と宣言
スクリプトは、プログラムなどを実行するように見えます。実際、SQL Server 2000の分析サービスと同じ概念 (パス順序や解決順序など) は適用されていますが、さらに目立たなくなります。実際には、MDX スクリプトは "実行" されていません。MDX スクリプトは、宣言済みの、常に有効なコマンドの集合です。キューブのコンテンツは、必ずスクリプトと整合性があります。
パス
パス 0 では、キューブには、ファクトおよび書き戻しデータのみが含まれています。スクリプトは、パス 0 後のデータを設定します。
スクリプトの代入、固定、および計算ステートメントそれぞれによって、新しいパスが作成されます。
計算されるメンバは、作成されるパスに関係なく、すべてのパスに存在します。
スクリプトが存在しない
スクリプトが定義されていない場合、キューブは、Calculate という 1 つのコマンドを含む既定の潜在的なスクリプトを想定します。
スクリプトが存在しても空の場合、このスクリプトを使用しても何も計算されません。
計算の作成
計算されるセルの簡単な定義方法は、次のとおりです。
<subcube definition> = <expression>;
例 :
(Sales,Budget) = (Sales,Actual) * 1.2; Sales = Sales *1.2 ;
各代入では、独自のパスが作成されます。このパスにより、無限再帰が防止されます。
単式が原因で無限再帰が発生する場合には、前のパスの値が取得されます。以下に例を示します。
Sales = Sales * 1.2
上記の式は、次の式に相当します。
Sales = CalculationPassValue(Sales, -1, RELATIVE) * 1.2
パスへの明示的な参照は許可されていますが、スクリプトが変更されてもパス番号が変更されないため、この参照はお勧めしません。
計算はより高い粒度で結果を変更します。正確な定義方法は後で説明します。
スコープ
スコープは、ステートメントをサブキューブに制限します。スコープが指定されていない場合は、既定のスコープがキューブ全体に適用されます。
BNF
Scope(<subcube definition>); <statement> ... End Scope; <subcube definition> :== refer to the definition of a subcube
スコープの定義は静的です。たとえば、SoldTo および PurchasedFrom という 2 つの役割を果たす Customer ディメンションを含むキューブを考えてみます。顧客自身に売却した顧客のサブキューブを定義する場合、次のアプローチは、予想どおりに動作しません。
Scope (SoldTo.Name.Name.members); Scope(LinkMember(SoldTo.Name.CurrentMember, PurchasedFrom.Name)); ... End Scope; End Scope;
これは、2 番目のスコープ ステートメントが各セルで再評価されないため、動作しません。つまり、SoldTo.Name.CurrentMember という式は、元のスコープよりも動的ではありません。
例
次の複数の例は、Customer および Measures という 2 つのディメンションを持つキューブを基にしています。Measures ディメンションには、Sales という 1 つのメジャーがあります。Customer ディメンションには、Country および City (粒度属性) という 2 つの属性があります。さらに、この 2 つの属性の階層および Geography というユーザーの階層があります。Country には、USA および England というメンバが含まれ、City には、Seattle、Redmond、London、および Leeds というメンバが含まれています。以下のテーブルでは、スコープおよび代入への影響を示しています。
以下の例には、計算ステートメントがないことに注意してください。キューブ内のデータは集計されません。そのため、すべての変更は、代入のみが原因で発生します。
わかりやすくするために、ディメンション名はメンバ名から省略されています。
例 1
Scope(Customer.Country.Country.USA, *); Sales = 2; End Scope;
クエリは上記のとおりです。
属性の階層別にデータを参照すると、次のように表示されます。
|
Country.[(All)].[All] |
Country. Country.USA |
Country. Country.England |
---|---|---|---|
City.[(All)].[All] |
|
2 |
|
City.City.Seattle |
|
2 |
|
City.City.Redmond |
|
2 |
|
City.City.London |
|
|
|
City.City.Leeds |
|
|
|
Geography というユーザーの階層からデータを参照すると、次のように表示されます。
|
Sales |
---|---|
Geography.[(All)].[All] |
|
Geography.USA |
2 |
Geography.USA.Seattle |
2 |
Geography.USA.Redmond |
2 |
Geography.England |
|
Geography.England.London |
|
Geography.England.Leeds |
|
この例では、(City.London, Country.USA) で定義されたセルが存在しないため、そのセルに値はありません。
例 2
Scope(Customer.City.City.Redmond, *); Sales = 4; End Scope;
属性の階層内の Sales
|
Country.[(All)].[All] |
Country. Country.USA |
Country. Country.England |
---|---|---|---|
City.[(All)].[All] |
|
|
|
City.City.Seattle |
|
|
|
City.City.Redmond |
4 |
4 |
|
City.City.London |
|
|
|
City.City.Leeds |
|
|
|
セル (City.City.Redmond, Country.Country.England) が null のままであることに注意してください。このセルは存在しないので、計算による影響を受けません。
Geography というユーザーの階層で Sales を参照すると、次のように表示されます。
|
Sales |
---|---|
Geography.[(All)].[All] |
|
Geography.USA |
|
Geography.USA.Seattle |
|
Geography.USA.Redmond |
4 |
Geography.England |
|
Geography.England.London |
|
Geography.England.Leeds |
|
例 3
Scope(Geography.USA.Redmond, *) Sales = 32; End Scope;
|
Country.[(All)].[All] |
Country. Country.USA |
Country. Country.England |
---|---|---|---|
City.[(All)].[All] |
|
|
|
City.City.Seattle |
|
|
|
City.City.Redmond |
|
32 |
|
City.City.London |
|
|
|
City.City.Leeds |
|
|
|
|
Sales |
---|---|
Customer.Geography.[(All)].[All] |
|
Customer.Geography.USA |
|
Customer.Geography.USA.Seattle |
|
Customer.Geography.USA.Redmond |
32 |
Customer.Geography.England |
|
Customer.Geography.England.London |
|
Customer.Geography.England.Leeds |
|
入れ子になったスコープ
入れ子になったスコープ ステートメントは、(属性に再度スコープが設定されない限り) 親スコープを継承します。以下に例を示します。
Scope(Customers.Country.USA); Scope(Customers.State.Or); Scope(Customers.Gender.Male); <scope is USA, Or, Male> End Scope; End Scope; End Scope;
スコープ ステートメントは、親スコープに含まれている階層に再度スコープを設定できます。以下に例を示します。
Scope(Customers.Country.USA); Scope(Customers.State.Or); Scope(Customers.State.Wa); <scope is Wa, USA> End Scope; <scope is Or, USA> End Scope; End Scope;
This
This というキーワードは、現在のサブキューブを表します。たとえば、次のコードでは、USA および Canada の Sales を 2 に設定します。
Scope(Sales, {USA, Canada}); This = 2; End Scope;
This は代入の右辺では使用できないことに注意してください。
Freeze ステートメント
ユーザーは、スクリプトにおいて、式で既に使用されたセルの値を変更して、別のセルの結果を確定しようとすることがありますが、既に行った計算の結果を変更せずにこの変更を行おうとすることもあります。
BNF
Freeze [<subcube>]
Freeze ステートメントは、セルを現在の値に固定します。他のセルを変更しても、影響はありません。
以下に例を示します。
B = 2; A = B; B = 3;
この時点で、A および B は両方とも 3 です。
B = 2; A = B; Freeze(A); B = 3;
この時点では、A は 2、B は 3 になります。
つまり、論理的には、パス 'p' 上の Freeze(<scope>) は、CalculationPassValue(<scope>, p, ABSOLUTE) という式をセルに割り当てることに相当します。
Calculate ステートメント
非リーフ セルのセルの計算は、キューブのディメンションの構造で示されています。ほとんどの場合、単純な集計ですが、ディメンションは単項演算子およびカスタム メンバとレベルの計算を定義できます。
さらに、各ディメンションは別の式を含めることができるため、その式を適用する順序によって、集計結果が変わる場合があります。Calculate コマンドは、キューブの既定の動作に応じてキューブを集計する方法を提供します。また、このコマンドを使用して、ディメンションの集計の順序を細かく制御できます。
非リーフ セルのコンテンツは、Calculate コマンドが適用される前は null です。つまり、Calculate コマンドを使用してセルに式を設定するまで、セルには式が含まれません。
BNF
Calculate;
Calculate コマンドは、計算されるメンバに影響しません。
Root
各属性の All メンバの交差部分に組を返します。属性に All メンバが含まれていない場合は、Root が既定のメンバを返します。
BNF
Root()
キューブ内の各属性の All メンバの交差部分に組を返します。All メンバがない場合は、最上位レベルのメンバが返されます。
Root(<dimension>)
ディメンション内の各属性の All メンバの交差部分に組を返します。
Root(<tuple>)
組に含まれている各属性の All メンバの交差部分に組を返します。
たとえば、全製品の利益率と比較して特定の製品 SKU の利益率を計算する計算されるメンバは、以下のようになります。
Create Member [Profit%] AS ([Profit %], [Product].[SKU].[SKU].currentmember) / ([Profit %], Root(Product))
Root は、現在のメンバのコンテキストで動作します。本来、これはすべての階層から現在のメンバの先祖を取得しています。すべての階層に All メンバが存在する場合、これは実に重要な All メンバです。ただし、All 以外のメンバの場合、現在のメンバの先祖に移動します。以下に例を示します。
Root(Time) は、time.currentmember が [25-Feb-2002] の場合に [2002] を返します。
キューブの集計方法
ほとんどの場合、キューブの集計は "単に規則的に行われるだけ" です。ただし、複雑なことをしようとする場合、次のルールを知っていると役立ちます。
最後のパスが優先される
複数の代入を同じセルに適用すると、必ず最後のパスが優先されます。
これは、代入のスコープのセルおよびそれ以上のセルに適用されます。たとえば、次のスクリプトを考えてみます。
Calculate; (Customer.Name.[All], Customer.City.[All], Customer.State.[All], Customer.Country.[All]) = 100; (Customer.Name.[Richard], Customer.City.[Sammamish], Customer.State.[Wa], Customer.Country.[USA]) = 1;
(Customer.Name.[All], Customer.City.[All], Customer.State.[All], Customer.Country.[All]) の値は、Richard 以外の顧客のファクト テーブルのデータに 1 を加えた値になります。より粒度の低い代入からの集計は、より粒度の高い以前のパスの代入より優先されます。
最も近いパスが優先される
最後のパスが優先されるルールは、代入に適用されますが、単項演算子およびカスタム メンバの式などのディメンションの計算には適用されません。代わりに、最も近いパスが優先されるルールが適用されます。
セルがディメンションの計算および代入を超える場合、セルは最も近い計算から評価されます。
たとえば、単項演算子を含むアカウントの階層および 2 つのメンバを含む製品の階層を含む、独自に作成したキューブを考えてみます。計算ステートメントにより、次のようにファクト データが集計されます。
|
All Products |
Baked Goods |
Drinks |
---|---|---|---|
All Accounts |
5 |
1 |
4 |
+Revenue |
12 |
4 |
8 |
- Expense |
7 |
3 |
4 |
ここで、次の代入による影響を考えてみます。
|
All Products |
Baked Goods |
Drinks |
---|---|---|---|
All Accounts |
5 |
1 |
100 |
+Revenue |
12 |
4 |
8 |
- Expense |
7 |
3 |
4 |
セル (Account.[All Accounts], Products.[All Products]) の値は 5 のままです。これは、単項演算子が最も近く (右上!) にあるためです。
代わりに、次の代入を考えてみます。
|
All Products |
Baked Goods |
Drinks |
---|---|---|---|
All Accounts |
-991 |
1 |
-992 |
+Revenue |
12 |
4 |
8 |
- Expense |
1003 |
3 |
1000 |
(Account.Expense, Products.[All Products]) の値は代入で集計されます。この代入は粒度が高く、他の計算の影響は受けません (単項演算子は、メンバをその親に集計する方法に影響しますが、メンバ自体での計算には影響しません)。
いわゆるディメンションの計算方法 (単項演算子およびカスタム メンバの式) の違いにより、代入を使用して、ディメンションの計算を純粋にエミュレートすることはできません。
Beta 2 で発生する可能性がある問題
Beta 2 では、動作に問題があるように見える部分があります。発生しうる問題について以下に説明します。
IgnoreUnrelatedDimensions
メジャー グループの IgnoreUnrelatedDimensions プロパティは、メジャー グループの自動 validmeasure に似ています。IgnoreUnrelatedDimensions プロパティは、結果を返すことに関連付けられていないディメンションのメンバによって、メジャーをクエリすることを意味します。たとえば、顧客に関連しないメジャー グループがあり、そのメジャー グループから顧客別にメジャーをクエリすると、customer.currentmember が All メンバであるかのようにデータが表示されます。この現象を回避する場合は、このプロパティの値を False に変更します。
MdxMissingMemberMode
このディメンション プロパティが True (Measure ディメンション以外のディメンションでは既定値) の場合、メンバが存在しないディメンションに解決できるメンバは単純に無視されます。その結果、間違ったメンバを含むスクリプトまたはクエリは、ただそのメンバを除外します。この機能の目的は、ディメンションの変更に対して格納されたクエリを支援することです。この設定を行わない場合は、ディメンションで値を変更してください。
データが集計されない
すべてのディメンション内の属性がメジャー グループにバインドされた属性に関連していないことを確認します。データは、バインドされた属性から、メジャー グループの粒度属性に直接または間接的に関連する属性にのみ集計されます。
セマンティクスを上書きする
属性のメンバを上書きすると、そのメンバが別の属性の 1 つのメンバと合わせて存在する場合のみ、両方のメンバが上書きされることが予想されます。たとえば、Customer.City.Seattle を上書きすると、State 属性も自動的に上書きされることが予想されますが、実際はそうではありません。以下に例を示します。
WITH MEMBER measures.x AS (Customers.City.Seattle, measures.[Profit])
SELECT measures.x on COLUMNS, Customers.State.State.Members on ROWS FROM sales
結果は、次のようになります。
<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th><p> </p></th>
<th><p> </p></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>Customers.State,BC</p></td>
<td><p> </p></td>
</tr>
<tr class="even">
<td><p>Customers.State.WA</p></td>
<td><p>100</p></td>
</tr>
<tr class="odd">
<td><p>Customers.State.Or</p></td>
<td><p> </p></td>
</tr>
<tr class="even">
<td><p>Customers.State.Ca</p></td>
<td><p> </p></td>
</tr>
</tbody>
</table>
ワシントン州 (WA) 以外の州の値は null です。これは、Seattle がこのような州に存在せず、上書きされないからです。
別の属性が上書きされるときに、ある属性が自動的に上書きされない場合、1 つ以上の属性が定義されると、ユーザーの階層の座標を判断できなくなることがあります。たとえば、Geography 階層で、組 (Customer.Country.All, Customer.State.All, Customer.City.All, Customer.\[Name\].Richard) にはどのメンバが対応しているでしょうか? 1 つのメンバではありません。このような状況が発生する場合は、"ギャップのルール" を使用して、階層の現在のメンバを決定します。
#### ギャップのルール
階層のメンバが存在しない場合、または個別の階層で作成された計算されるメンバの場合、最低レベルから最高レベルへ、階層のメンバが見つかるまで、メンバを All メンバと置き換えます。
これは、Beta 3 で対処する予定です。
クエリ軸が独立して解決される
軸は、互いに独立して解決されます。これにより、いくつかの影響が付随して発生します。次のことが予想されます。
Select Customer.State.State.members on 0 from sales where Customer.Country.Country.Canada
上記のコマンドは、この条件を満たす Canada の州のみを返します。実際には、すべての州が返されます。
これは、Beta 3 で対処する予定です。
次のクエリを考えてみます。
SELECT measures.members on ROWS, nonemptycrossjoin(Customer.State.State.members,
Product.Brand.Brand.members) on COLUMNS FROM sales
メジャーが nonemptycrossjoin 関数で使用されなかったことに注意してください。既定のメジャーが使用されます。Customer ディメンションおよび Product ディメンションに関連しないメジャー グループに既定のメジャーがある場合、メンバは列軸に返されません。
これは、Beta 3 で対処する予定です。
集計不可能な階層の既定のメンバ
属性が集計不可能な場合は、依然として、メンバのいずれかが既定のメンバである必要があります。この既定のメンバはクエリで上書きされる場合を除いて、実在の問題の原因になることがあります。
たとえば、FiscalYear および CalendarYear という 2 つの属性を持つ Time ディメンションを考えてみます。これらの属性が両方とも集計不可能な場合、両方の属性を明示的に含まない任意のクエリは、(サーバーで取得された) 既定のメンバと一緒に存在しない属性のメンバのデータを取り出します。Beta 2 では、この問題を解決するために、All メンバを保持し続ける必要があります。
複数のメジャー グループ間の Leaves 関数
Leaves 関数は、キューブまたはディメンションのリーフ メンバを返します。この関数は、さまざまなメジャー グループが現在のスコープのディメンションに異なる粒度を設定している場合、エラーを返します。
これは、Beta 3 で対処する予定です。
たとえば、Budget および Actual という 2 つのメジャー グループを考えてみます。Budget は Time.Month で Time の粒度を設定し、Actual は Time.Day で粒度を設定します。次のスクリプトでは、エラーが発生します。
Scope Scope(Leaves(Time));
<some assignment> End Scope;
時間のリーフを解決できないことが原因で、エラーが発生します。これは日と月のどちらでしょうか? これを解決するには、最初に、共通の時間の粒度を共有する、メジャー グループのメジャーにスコープを設定します。
<pre IsFakePre="true" xmlns="http://www.w3.org/1999/xhtml">Scope (measures.ActualValue);
Scope( Leaves(Time) ); <some assignment> End Scope; End Scope;