web-dev-qa-db-ja.com

UNIONおよびDESCENDANTSと組み合わせたAnalysis Serviceのメジャーの誤った集計

更新:問題を再現する簡単な例を提供しようとすると、データベースにレベラーが見つかり、この問題が発生しました。したがって、この新しい発見を反映するために、この質問を更新しました。以下に、この問題を再現するデータベースをセットアップするためのスクリプトを示します。

サーバーバージョン2008および2012でAnalysis Servicesの奇妙な動作が発生しています。

私のASデータベースでは、次のようなベースメジャーを持つキューブを定義しました。

_AggregateFunction: Min;
Name: Existing Data
_

ご覧のとおり、集計関数はMinです。

対応する_existing_data_列を含むファクトテーブルには、_0_または_1_の値のみが含まれます。目標は、データ選択にゼロ値にリンクされているカテゴリが含まれるとすぐにゼロを返すことです。このマトリックスは、別のファクトテーブルに格納されている実際のファクト内の、データが収集された/されていない領域を示します。そのため、選択された領域にケースがないか、選択された領域があるため、結果がゼロかどうかを区別できます。まだ集まった事例はありません。

次のクエリを実行すると、選択したカテゴリごとに1が返されます。

_WITH
   SET [adhoc] AS 'UNION(
     DESCENDANTS([Gebiete].[Hierarchie].[Bezirk].[010],[Gebiete].[Hierarchie].[Landkreis]),
     DESCENDANTS([Gebiete].[Hierarchie].[Bundesland].[10],[Gebiete].[Hierarchie].[Landkreis])
   )'
SELECT [adhoc] ON 0
FROM [Testdb]
WHERE ([Measures].[Existing Data])
_

結果

_01001    01002    10041    10042
1        1        1        1
_

このクエリを次のように変更すると、Min() functionによって集計されたすべての値が1になるため、結果として1を含む1つのセルが期待されます(以前の結果と比較)。

_WITH
    SET [adhoc] AS 'UNION(
      DESCENDANTS([Gebiete].[Hierarchie].[Bezirk].[010],[Gebiete].[Hierarchie].[Landkreis]),
      DESCENDANTS([Gebiete].[Hierarchie].[Bundesland].[10],[Gebiete].[Hierarchie].[Landkreis])
    )'
    MEMBER [Gebiete].[Hierarchie].[adhoc] AS 'Aggregate([adhoc])'
SELECT {[Gebiete].[Hierarchie].[adhoc]} ON 0
FROM [Testdb]
WHERE ([Measures].[Existing Data]);
_

しかし、代わりに私は得ています

_adhoc
0
_

_[Gebiete].[Hierarchie].[adhoc]_メンバーでAggregate関数を明示的にMinを呼び出すように変更すると、次の望ましい結果が得られます

_adhoc
1
_

クエリ:

_WITH
    SET [adhoc] AS 'UNION(
      DESCENDANTS([Gebiete].[Hierarchie].[Bezirk].[010],[Gebiete].[Hierarchie].[Landkreis]),
      DESCENDANTS([Gebiete].[Hierarchie].[Bundesland].[10],[Gebiete].[Hierarchie].[Landkreis])
    )'
    MEMBER [Gebiete].[Hierarchie].[adhoc] AS 'Min([adhoc])'
SELECT {[Gebiete].[Hierarchie].[adhoc]} ON 0
FROM [Testdb]
WHERE ([Measures].[Existing Data]);
_

これを追跡して、ファクトデータがGebieteディメンションにどのようにリンクされているか、およびこのディメンションがどのように入力されているかに何らかの形で関連していることを確認しました。このディメンションには、Landkreis(最下位レベル)、Bezirk、およびBundeslandの3つのレイヤーがありますが、ファクトテーブルは中間レベル(Bezirk)とのみリンクされています。すべての関連テーブルのこの図を参照してください。

OLAP source DB tables

_01_ブランチの下に複数のノードがあるこのディメンションの3つのレベルすべてにデータを入力すると、問題が発生します。

Gebiete dimension populated with items that cause the issue

代わりに、_01_ブランチの下にノードが1つだけあり、_10_ブランチの下に1つまたは複数のノードがあるディメンションを設定しますか?.

Gebiete dimension populated with items that cause the issue

したがって、それはおそらくUNION、DESCENDANTS、Aggregateの組み合わせ、およびディメンションテーブルへの入力方法に関するバグだと思います。私が正しいかどうか、これが本当にバグかどうか、またはMDXクエリが間違っているかどうかを確認してください。

以下に、問題を再現するデータベースをセットアップするためのすべての情報を示します。

_-- Fact
if exists (select * from dbo.sysobjects where id = object_id(N'dbo.fact_falldaten_existing_data') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table dbo.fact_falldaten_existing_data;

-- Area
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sf_gebiet_landkreis]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[sf_gebiet_landkreis];
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sf_gebiet_bezirk]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[sf_gebiet_bezirk];
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sf_gebiet_bundesland]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[sf_gebiet_bundesland];

GO

create table dbo.sf_gebiet_bundesland(
    id numeric(7, 0) primary key,
    shortname varchar(255) null,
    longname varchar(255) null,
    description varchar(255) null,
    geo_id numeric(10, 0) null,
    gkz varchar(10) null,
    parent_id numeric(7, 0)
);

create table dbo.sf_gebiet_bezirk(
    id numeric(7, 0) primary key,
    shortname varchar(255) null,
    longname varchar(255) null,
    description varchar(255) null,
    geo_id numeric(10, 0) null,
    gkz varchar(10) null,
    parent_id numeric(7, 0) references sf_gebiet_bundesland(id)
);

create table dbo.sf_gebiet_landkreis(
    id numeric(7, 0) primary key,
    shortname varchar(255) null,
    longname varchar(255) null,
    description varchar(255) null,
    geo_id numeric(10, 0) null,
    gkz varchar(10) null,
    parent_id numeric(7, 0) references sf_gebiet_bezirk(id)
);

GO

INSERT dbo.sf_gebiet_bundesland (id, shortname, longname, description, geo_id, parent_id) VALUES (2034, '01', 'Schleswig-Holstein', '', 16, 2032);
INSERT dbo.sf_gebiet_bundesland (id, shortname, longname, description, geo_id, parent_id) VALUES (2043, '10', 'Saarland', '', 9, 2032);

INSERT dbo.sf_gebiet_bezirk (id, shortname, longname, description, geo_id, parent_id) VALUES (2051, '010', 'Schleswig-Holstein alle Bezirke', '', 441, 2034);
INSERT dbo.sf_gebiet_bezirk (id, shortname, longname, description, geo_id, parent_id) VALUES (2079, '100', 'Saarland alle Bezirke', '', 446, 2043);

INSERT dbo.sf_gebiet_landkreis (id, shortname, longname, description, geo_id, parent_id) VALUES (2539, '01001', 'Flensburg', '', 881, 2051);
INSERT dbo.sf_gebiet_landkreis (id, shortname, longname, description, geo_id, parent_id) VALUES (2540, '01002', 'Kiel', '', 882, 2051);

INSERT dbo.sf_gebiet_landkreis (id, shortname, longname, description, geo_id, parent_id) VALUES (2858, '10041', 'Stadtverband Saarbrücken', '', 1200, 2079);
INSERT dbo.sf_gebiet_landkreis (id, shortname, longname, description, geo_id, parent_id) VALUES (2859, '10042', 'Merzig-Wadern', '', 1201, 2079);

-- Fact Data
CREATE table dbo.fact_falldaten_existing_data(
    bezirk          numeric(7)  references sf_gebiet_bezirk(id),
    existing_data   numeric(1)
);

GO

INSERT INTO fact_falldaten_existing_data (bezirk,existing_data) VALUES(2079,1);
INSERT INTO fact_falldaten_existing_data (bezirk,existing_data) VALUES(2051,1);

-- Comment this out to solve the issue
INSERT dbo.sf_gebiet_bezirk (id, shortname, longname, description, geo_id, parent_id) VALUES (2951, '01', 'Schleswig-Holstein unbekannter Bezirk', '', 3006, 2034);
INSERT dbo.sf_gebiet_landkreis (id, shortname, longname, description, geo_id, parent_id) VALUES (2502, '01', 'Schleswig-Holstein unbekannter Landkreis', '', 3000, 2951);
INSERT INTO fact_falldaten_existing_data (bezirk,existing_data) VALUES(2951,0);

--INSERT dbo.sf_gebiet_bezirk (id, shortname, longname, description, geo_id, parent_id) VALUES (2956, '10', 'Saarland unbekannter Bezirk', '', 3011, 2043);
--INSERT dbo.sf_gebiet_landkreis (id, shortname, longname, description, geo_id, parent_id) VALUES (2528, '10', 'Saarland unbekannter Landkreis', '', 3024, 2956);
--INSERT INTO fact_falldaten_existing_data (bezirk,existing_data) VALUES(2956,1);
_

ソースデータベースと展開ターゲットを適切に変更する必要があるSQL Serverデータツールプロジェクトをここで見つけます。 SSDTプロジェクトのダウンロード

2
David

多次元Contosoキューブを使用して、Min Inventory Day in Stockのメジャーを持つものを複製しようとしましたが、問題は発生しませんでした。 [アドホック]を集計するときは 現在のコンテキスト に関係していると思います。正確に複製するのに十分な情報がありません。しかし、このフレーズは MIN()の仕様 を見て、私の目に留まりました。

数値式が指定されていない場合、指定されたセットは、セットのメンバーの現在のコンテキストで評価され、その評価から最小値を返します。

最初に、いくつかの考え:

  • 注として、クエリ内の計算されたメンバーを一重引用符で囲む必要はありません。計算によってエラーがスローされない限り、それらが存在しても害はありませんが、 SSAS 2005以降では必要ありません であり、場合によってはメッセージを抑制できます。
  • 計算されるメンバーは実行時に評価されるため、キャッシュを利用することはできません。作業を スコープ付きスクリプトに移動し、計算されたメジャーをシンプルに保つ に移動することをお勧めします。または、可能であれば軸に移動して、クエリを複数回実行するときにクエリでキャッシュできるようにします。大規模なデータセットや非常に重要なデータがあり、すぐに返す必要がある場合は、計算されるメンバーの使用を変更することができます。
  • DESCENDANTSを含むUNIONは問題ありません。私は同様のことをすることができ、それは正しい結果を生み出しました。これは、集約されたメンバーの代わりにセットを使用して、期待どおりにすべてのメンバーが存在することを確認することで確認できます。でも、なぜそれを持っているのか少し困惑しています。私が間違っている場合は修正してください。ただし、ウェッサーエムスはニーダーザクセン州の一部だと思いました(ただし、ドイツの地理については完全には詳しくありません)。ヴェッサーエムスがニーダーザクセン州の一部である場合、ニーダーザクセン州の子孫を成し遂げ、組合を成し遂げなかった可能性があります。あなたの組合には何の問題もないので、それはここにもそこにもありません。クエリをできるだけ単純化したいだけです。
  • SSASは本当に寛大です。完全修飾メンバーを指定しないと、意味を解釈しようとします。たとえば、[Measures]。[HasData]ではなく[Has Data]を使用していて、セットと集約されたメンバーが両方[adhoc]であるとします。どこかに[HasData]と呼ばれるフィールドもある場合、それはあなたが何を意味したのか混乱する可能性があります。
  • SSASは最小値を計算するときにnullを無視します
  • すでにMIN()を実行するメジャー([メジャー]。[データがある])があるため、現在のコンテキストにある場合は AGGREGATE() を使用すると、引き続き最小化されます。
  • SQLのWHERE句とは異なり、MDX SELECTステートメントのWHERE句は、クエリの行軸に返されるものを直接フィルターすることはありません 。クエリの行軸または列軸に表示されるものをフィルタリングするには、FILTER、NONEMPTY、TOPCOUNTなどのさまざまなMDX関数を使用できます。たとえば、2006年に在庫がない場合でも、次のクエリでは2006がメンバーとして返されます。
 WITH SET [adhoc] AS 
 UNION(DESCENDANTS([Geography]。[Geography Hierarchy]。[Region Country Name]。[Germany]、
 [Geography]。[Geography Hierarchy]。[City Name])、
 DESCENDANTS([Geography]。[Geography Hierarchy]。[State Province Name]。[Lower Saxony]、
 [Geography]。[Geography Hierarchy]。 [市]))
メンバー[地理]。[地理階層]。[アドホック]としてMIN([アドホック])
選択{[日付]。[カレンダーYQMD]。[カレンダー年] .members} on 0 
 from [Operation] 
 where([Geography]。[Geography Hierarchy]。[adhoc]、[Measures]。[Inventory Min Day In Stock])

私のデータセットでは、私のファクトテーブルは[Measures]。[Inventory Min Day In Stock]を構成するデータの値が5しかありません。これは、すべて1の場合と似ています。

このクエリは、MIN([adhoc])とAGGREGATE([ad hoc])のどちらを使用しても、予想される同じ回答(5)を返します

WITH 
SET [adhoc1] AS 
UNION(DESCENDANTS([Geography].[Geography Hierarchy].[Region Country Name].[Germany], [Geography].[Geography Hierarchy].[City Name]), 
DESCENDANTS([Geography].[Geography Hierarchy].[State Province Name].[Lower Saxony], [Geography].[Geography Hierarchy].[City]))
MEMBER [Geography].[Geography Hierarchy].[adhoc] as Min([adhoc1])
SELECT {[Date].[Calendar YQMD].[Calendar Year].[Year 2008] } on 0
from [Operation]
where ([Geography].[Geography Hierarchy].[adhoc],[Measures].[Inventory Min Day In Stock])

私の最善のアドバイスは、いくつかの異なる方法で書き直すことです。計算されたメジャーが遅すぎない場合は、それらを使用して正しいコンテキストがあることを確認できます。

WITH 
MEMBER [Geography].[Geography Hierarchy].[adhoc] as Aggregate(UNION(DESCENDANTS([Areas].[Hierarchy].[Region].[Weser Ems],[Areas].[Hierarchy].[City]),DESCENDANTS([Areas].[Hierarchy].[State].[Lower Saxony],[Areas].[Hierarchy].[City])))
MEMBER [Measures].[Test] as Min([Geography].[Geography Hierarchy].[adhoc],[Measures].[HasData])
SELECT {[Time].[Hierarchy].[Year].[2008] } on 0
from [Incidence]
where ([Measures].[Test])
5
mmarie