web-dev-qa-db-ja.com

MDXに存在しないSQLに相当する(または同じ結果を達成する別の方法を見つける)

私は請負業者が多次元SSAS 2017でキューブを実装するのを手助けしようとしていますが、MDXでの経験があまりありません。

次のようなテーブルがあります。

enter image description here

目標は、フィルターが適用された後、[seq][Part]、およびPersonIDの各コンボごとに[CustomerID]が最も低い行のみをクエリに含めることです。値列を合計します。したがって、フィルターが適用されていない場合は、行1と3のみが返され、値列の合計は2になります。ただし、ユーザーが6月のデータのみをフィルターした場合、行2と3のみが返され、合計が返されます。値の列の1でなければなりません。

これをSQLで次のように実現しました。

SELECT SUM(Value) 
FROM (SELECT * 
 ,ROW_NUMBER() OVER (PARTITION BY CustomerID,PersonID, Part ORDER BY SEQ asc) AS Seq
 FROM Table WHERE DATEKeY BETWEEN @StartDate AND @EndDate
 )A
WHERE Seq=1;

しかし、請負業者はMDXランク関数のパフォーマンスに大きな問題を抱えています。 MDXの経験があまりないため、適切に機能する代替案があるかどうかを知るのに苦労しており、請負業者は私たちのビジネスニーズに一致する代替案を提供していません。

私が思いついた別のアプローチはこれです:

SELECT SUM(Value) 
FROM [Table]  AS A
WHERE DATEKey BETWEEN @StartDate AND @ENDDate 
AND CustomerID=@CustomerID 
AND NOT EXISTS(SELECT 1 FROM Table AS B 
                WHERE B.Part=A.Part
                  AND B.CustomerID=@CustomerID
                  AND B.PersonID=A.PersonID
                  AND B.SEQ<A.SEQ)

これは実際にはSQLの以前の方法よりも優れたパフォーマンスを発揮しますが、これ、以前のメソッド、または適切に機能するMDXの同等のロジックを実装する方法がわかりません。

キューブ全体を見ないとMDXを実行するのは難しいことはわかっていますが、このロジックに最適なパフォーマンスを提供する関数についての偽のコードまたはアドバイスだけが大きな助けになります。

3
schiznig

あなたが実際の立方体なしで試すのは難しいと言っているように、それはあなたの次元がどのようにレイアウトされているかに少し依存しますが、私はあなたが [〜#〜] bottomcount [ 〜#〜] 関数は、seqでメジャーを作成する場合に使用します。

BottomCount(Set_Expression、Count [、Numeric_Expression])

Set_expressionは、関心のあるディメンション間のcrossjoinであり、その式に基づいて dynamic set を作成できます。

の線に沿った何か

WITH DYNAMIC SET LowestSeq AS
BottomCount({Part.Members * Customer.Members * Person.Members})
   , 1  
   , [Measures].[seq])

PastebinなどでXMLAスクリプトとしてシナリオの小さな再現を公開した場合に役立ちます。 dsvがデータ​​を生成する名前付きクエリに基づいている場合、マシン上に同じキューブを簡単に作成できます。

MDXでシーケンスロジックを実行しないことをお勧めします。あなたはパフォーマンスに失望するでしょう。私は次のアプローチをお勧めします:

最初に、現在有効な値を示す1日あたりのパーツ/顧客/人ごとに1行を返すビュー(または、必要に応じて物理テーブル)を作成します。ビューは次のようになります。

select x.PersonID, x.Part, x.CustomerID, x.Value, d.DateKey
from (
    select *
    ,LEAD(x.DateKey,1,100000000) OVER (PARTITION BY CustomerID,PersonID, Part ORDER BY SEQ asc)-1 as EndDateKey
    from YourTable x
) x
join DimDate d on d.DateKey between x.DateKey and x.EndDateKey
where d.[Date] < getdate()

次に、その新しいビューをメジャーグループとしてキューブに読み込みます。 Sumメジャーの代わりに、AggregateFunction = FirstChildを使用してValue列でメジャーを使用します。これにより、2018年2月の合計は、2018年2月1日に有効であった行を反映します。

FirstChildはセミアディティブメジャーで、選択した日付範囲の最初のメンバーを返します。これを読むことをお勧めします ブログ投稿 日付ディメンションを適切にマークして、機能するようにします。

直感に反して、データ量が急増している場合でも、キューブの処理時間中およびクエリ時間中にすべてのハードワークが行われるため、このアプローチはキューブでより適切に実行されます。

私の推奨に従う場合、最終的に何行になるかを計算してください。うまくいけば、それは妥当な数の行です(たとえば、1億以下、または適切なハードウェアを使用している場合は10億以上)。それが不合理な行数(100,000,000,000など)である場合、実装がはるかに複雑な多対多の日付範囲ディメンションなどの他のオプションがあります。私の推奨が適切でない限り、私はそのアプローチを推奨しません。

1
GregGalloway