次の方法で共有


パス順序と解決順序の概要 (MDX)

MDX スクリプトの結果としてキューブが計算される場合、計算に関連するさまざまな機能の使われ方によっては、キューブは多数の計算段階をたどることがあります。それらの各段階は、計算パスと呼ばれます。

計算パスは、計算パス番号と呼ばれる序数で表すこともできます。キューブのセルすべてを完全に計算するために必要な計算パスの数を、キューブの計算パスの深さと呼びます。

パス 0 に影響するのはファクト テーブルと書き戻しデータだけです。スクリプトがデータを設定するのはパス 0 の後です。ステートメント内に代入や計算ステートメントがある場合、新しいパスが作成されます。MDX スクリプト以外では、絶対パス 0 への参照がある場合、それはキューブに対するスクリプトによって最後に作成されたパスを意味します。

計算されるメンバはすべてのパスで作成されますが、式が適用されるのは現在のパスです。以前のパスには計算されるメジャーが含まれますが、値は NULL です。

解決順序

解決順序は、競合する式がある場合に計算の優先順位を決定します。1 つのパスの中では、解決順序によって以下の 2 つの順序が決まります。

  • ディメンション、メンバ、計算されるメンバ、カスタム ロールアップ、および計算されるセルが MicrosoftSQL ServerAnalysis Services によって評価される順序。

  • カスタム メンバ、計算されるメンバ、カスタム ロールアップ、および計算されるセルが Analysis Services によって計算される順序。

最も高い解決順序を持つメンバが最も優先されます。

注意注意

この優先順位に関する例外は、Aggregate 関数です。Aggregate 関数を使用して計算されるメンバの解決順序は、交差するどの計算されるメジャーの解決順序よりも低くなります。

計算の優先順序

計算の優先順序は、現在のセルで定義されている式に対して値が取得される順序を定義します。計算の優先順序は次のアルゴリズムに従って解決されます。

  1. 粒度が現在のセル以下であるすべての計算から計算リスト (CL) が作成されます。

  2. CL の計算が、Highest Wins (HW : 解決順序の高いものを優先) と Closest Wins (CW : 宣言の近いものを優先) に分類されます。

    1. カスタム ロールアップ、単項演算子、準加法メジャー、Freeze は CW です。

    2. 他のすべての計算は HW です。

  3. すべての HW から、パスで順序付けされた順序付き計算リスト (OCL) が作成されます。

  4. 残りの CW のそれぞれが次のように処理されます。

    1. OCL (降順) の各計算 (C) について次の処理が行われます。

    2. CW が C より現在のセルに近い場合は、CW を OCL に挿入し、次の CW に進みます。

    3. CW が C より高いパスにある場合は、CW を OCL に挿入し、次の CW に進みます。

    4. 次の C に進みます。

  5. OCL の一番上の計算の粒度が現在のセルと同じでない場合は、集計関数を使用して集計値を計算します。

解決順序の値と優先順位

解決順序は、-8,181 ~ 65,535 の値をとります。この範囲内で、いくつかの解決順序の値は、次の表のように特定の種類の計算に対応しています。

計算

解決順序

カスタム メンバ式

-5119

単項演算子

-5119

表示部分の合計計算

-4096

その他のすべての計算 (特に指定されていない場合)

0

解決順序の値を設定するときは、正の整数のみを使用することを強くお勧めします。前の表に示されている解決順序の値よりも低い値を割り当てると、計算パスが予測不能になることがあります。たとえば、計算されるメンバの計算に、解決順序の値として既定のカスタム ロールアップ式の値である -5119 より低い値を割り当てるとします。このように低い解決順序の値を持つ計算されるメンバはカスタム ロールアップ式より先に計算され、正確な結果が得られないことがあります。

解決順序の作成と変更

キューブ デザイナでは、[計算] ペインで計算の順序を変更することによって、計算されるメンバと計算されるセルの解決順序を変更できます。

MDX では、計算されるメンバや計算されるセルを作成または変更するときに SOLVE_ORDER キーワードを使用できます。

解決順序の例

解決順序がどれほど複雑なものになることがあるかを示すために、個別のクエリとしては解決順序を考慮する必要のない 2 つのクエリで始まる一連の MDX クエリを次に示します。それらの 2 つのクエリを組み合わせると、解決順序を考慮しなければならないクエリになります。

クエリ 1 - 収益と経費の差

1 番目の MDX クエリとして、半年ごとの収益と経費の差を調べるために、次の例のような単純な MDX クエリを作成します。

WITH
MEMBER [Time].[Year Difference] AS
   [Time].[2nd half] - [Time].[1st half]
SELECT 
   { [Account].[Income], [Account].[Expenses] } ON COLUMNS,
   { [Time].[1st half], [Time].[2nd half], [Time].[Year Difference] } ON ROWS
FROM Financials

このクエリでは、計算されるメンバは Year Difference の 1 つだけです。計算されるメンバが 1 つだけなので、キューブで計算されるメンバが使用されない限り、解決順序を考慮する必要はありません。

この MDX クエリは、次の表のような結果セットを作成します。

 

Income

Expenses

1st half

5000

4200

2nd half

8000

7000

Year Difference

3000

2800

クエリ 2 - 経費差し引き後の純利益のパーセンテージ

2 番目のクエリとして、半年ごとの経費差し引き後の純利益のパーセンテージを調べるために、次の MDX クエリを使用します。

WITH
MEMBER [Account].[Net Income] AS
   ([Account].[Income],  [Account].[Expenses]) / [Account].[Income]
SELECT
   { [Account].[Income], [Account].[Expenses], [Account].[Net Income] } ON COLUMNS,
   { [Time].[1st half], [Time].[2nd half] } ON ROWS
FROM Financials

前のクエリと同様、この MDX クエリでも計算されるメンバは Net Income の 1 つだけなので、解決順序の複雑さはありません。

この MDX クエリは、次の表のようなわずかに異なる結果セットを作成します。

 

Income

Expenses

Net Income

1st half

5000

4200

0.16

2nd half

8000

7000

0.125

1 番目のクエリと 2 番目のクエリの結果セットの違いは、計算されるメンバの配置位置の違いによるものです。1 番目のクエリでは、計算されるメンバは ROWS 軸の一部ですが、2 番目のクエリの場合は COLUMNS 軸の一部になっています。次の例で、2 つの計算されるメンバを 1 つの MDX クエリで組み合わせて使用するときに、この配置位置の違いが重要になります。

クエリ 3 - 年に関する差と純利益の計算の組み合わせ

最後のクエリでは、前の 2 つの例を 1 つの MDX クエリに結合します。このとき、解決順序が重要になります。計算が正しい順序で確実に行われるように、SOLVE_ORDER キーワードを使用して計算の行われる順序を定義します。

SOLVE_ORDER キーワードは、MDX クエリまたは CREATE MEMBER コマンド内の計算されるメンバの解決順序を指定します。SOLVE_ORDER キーワードで使用される整数値は相対値であり、0 で始まる必要はありません。また、連続値である必要もありません。この値は、より高い値を持つメンバを計算して得られる値に基づいてそのメンバを計算するように MDX に指示するだけです。計算されるメンバの定義に SOLVE_ORDER キーワードが含まれていない場合、その計算されるメンバの既定値は 0 です。

たとえば、最初の 2 つの例のクエリで使用されている計算を結合すると、計算対象となる 2 つのメンバである Year Difference と Net Income は、MDX クエリの例の結果データセット内にある 1 つのセルで交差します。Analysis Services がこのセルをどのように評価するかを決定する唯一の方法は、解決順序を指定することです。このセルを作成するために使用する数式は、2 つの計算されるメンバの解決順序に応じて、異なる結果を作成します。

まず、最初の 2 つのクエリで使用されている計算を次の MDX クエリのように結合してみます。

WITH
MEMBER [Time].[Year Difference] AS
   '[Time].[2nd half] - [Time].[1st half],
   SOLVE_ORDER = 1
MEMBER [Account].[Net Income] AS
   '([Account].[Income] - [Account].[Expenses]) / [Account].[Income]',
   SOLVE_ORDER = 2
SELECT
   { [Account].[Income], [Account].[Expenses], [Account].[Net Income] } ON COLUMNS,
   { [Time].[1st half], [Time].[2nd half], [Time].[Year Difference] } ON ROWS
FROM Financials

この結合された MDX クエリの例では、Net Income が最も高い解決順序を持つため、2 つの式が相互作用するときに優先されます。Analysis Services は、問題のセルを Net Income の数式を使用して評価します。この入れ子にされた計算は、次の表に示すような結果を作成します。

 

Income

Expenses

Net Income

1st half

5000

4200

0.16

2nd half

8000

7000

0.125

Year Difference

3000

2800

0.066

共有されるセルの結果は、Net Income の数式に基づいています。つまり、Analysis Services は共有されるセルの結果を Year Difference のデータを使用して計算し、次の数式を作成します。結果はわかりやすくするために丸めてあります。

((8000 - 5000) - (7000 - 4200)) / (8000 - 5000) = 0.066 

または

(3000 - 2800) / 3000 = 0.066

しかし、MDX クエリ内の計算されるメンバの解決順序を入れ替えると、Analysis Services は共有されるセルの結果を異なる方法で計算します。次の結合された MDX クエリでは、計算されるメンバの解決順序を逆にしています。

WITH
MEMBER [Time].[Year Difference] AS
   '[Time].[2nd half] - [Time].[1st half],
   SOLVE_ORDER = 2
MEMBER [Money].[Net Income] AS
   '([Money].[Income] - [Money].[Expenses]) / [Money].[Income]',
   SOLVE_ORDER = 1
SELECT
   { [Money].[Income], [Money].[Expenses], [Money].[Net Income] } ON COLUMNS,
   { [Time].[1st half], [Time].[2nd half], [Time].[Year Difference] } ON ROWS
FROM TestCube

計算されるメンバの順序が入れ替わったため、Analysis Services は Year Difference の数式を使用してセルを評価します。結果は次の表のようになります。

 

Income

Expenses

Net Income

1st half

5000

4200

0.16

2nd half

8000

7000

0.125

Year Difference

3000

2800

-0.035

このクエリは Year Difference の数式を使用し、Net Income のデータをその数式に使用するため、共有されるセルの数式は次の計算のようになります。

((8000 - 7000) / 8000) - ((5000 - 4200) / 5000) = -0.035 

または

0.125 - 0.16 = -0.035

その他の注意点

解決順序の問題は、計算されるメンバ、カスタム ロールアップ式、または計算されるセルの関係するディメンションが多数あるキューブの場合は特に、非常に複雑になります。Analysis Services が MDX クエリを評価するとき、Analysis Services は、MDX クエリで指定されているキューブのディメンションも含め、特定のパスに関係するものすべての解決順序の値を考慮します。