classmethod %OnGetFilterList(Output pFilters As %List,pDataSourceName As %String = "") As %Status
pFilters は以下のノードの配列です。
pDataSourceName は、将来使用するためのものです。
例えば、以下の %OnGetFilterList() は New Filter という名前のフィルタを追加します。
ClassMethod %OnGetFilterList(Output pFilters As %List, pDataSourceName As %String = "") As %Status
{
set newfilter=$LB("New Filter","New Filter Display Name",,0)
set pFilters($I(pFilters))=newfilter
}
別の例として、以下の %OnGetFilterList() は、ユーティリティ・メソッドを使用して、Patients キューブのすべてのレベルをフィルタとして定義します。ユーティリティ・メソッド %GetFiltersForDataSource() (%DeepSee.Dashboard.UtilsOpens in a new tab 内) は、%OnGetFilterList() で必要な形式でフィルタのリストを返します。
ClassMethod %OnGetFilterList(Output pFilters As %List, pDataSourceName As %String = "") As %Status
{
set tSC = ##class(%DeepSee.Dashboard.Utils).%GetFiltersForDataSource("patients.cube",.tFilters)
quit:$$$ISERR(tSC)
set i = ""
for {
set i = $order(tFilters(i), 1, data)
quit:i=""
set pFilters($i(pFilters)) = $lb($lg(data,2), $lg(data,1),,1)
}
quit $$$OK
}
valueList 属性を使用したフィルタ項目のリストのハードコード
フィルタ項目のリストを構築する別の方法は、<filter> 要素の valueList 属性を指定することです。フィルタ項目の論理名のコンマで区切られたリストを使用します。このリストの順序によって、フィルタがフィルタ項目のリストを制御する順序が決まります。
以下に例を示します。
<filter name="ZipCode"
valueList="&[36711],&[34577],&[38928],&[32006],&[32007]"
displayList="36711,34577,38928,32006,32007"
/>
この属性は、sql 属性よりも優先されます。
この属性を指定する場合、上の例に示すように、displayList 属性も指定できます。指定する場合、表示名のコンマで区切られたリストを使用する必要があります。この属性を指定しない場合、論理名が表示名としても使用されます。
sql 属性を使用したフィルタ項目のリストの取得
フィルタ項目のリストを構築する別の方法は、<filter> 要素の sql 属性を指定することです。指定した場合、これは SQL クエリにする必要があります。このクエリは、1 列または 2 列を返すことができます。返されるデータセットの最初の列は、フィルタ項目の論理名を提供する必要があります。2 番目の列を含める場合、これは対応する表示名を提供します。2 番目の列を含まない場合、論理名が表示名としても使用されます。
以下に例を示します。
<filter name="ZipCode1" sql="SELECT DISTINCT PostalCode FROM BI_Study.City"/>
sql 属性を指定する場合は、displayList 属性および valueList 属性は指定しないでください (前のサブセクションを参照してください)。
カスタム・ロジックを使用して実行時にフィルタ項目のリストを構築
フィルタ項目のリストを構築する別の方法は、%OnGetFilterMembers() および独自のロジックを実装し、リストを作成することです。以下に例を示します。
ClassMethod %OnGetFilterMembers(pFilter As %String, Output pMembers As %List, pSearchKey As %String = "") As %Status
{
Set status = $$$OK
Try {
If (pFilter = "AgeGroup") {
set pFilterSpec="[AgeD].[h1].[Age Group]"
} Elseif (pFilter="Gender") {
set pFilterSpec="[GenD].[h1].[Gender]"
} Elseif (pFilter="ZipCode") {
set pFilterSpec="[HomeD].[h1].[ZIP]"
}
do ##class(%DeepSee.KPI).%GetMembersForFilter("Patients",pFilterSpec,.pMembers,pSearchKey)
}
Catch(ex) {
Set status = ex.AsStatus()
}
Quit status
}
別の方法として、レベル・メンバを保持するディメンジョン・テーブルでクエリを実行することができます。(ディメンジョン・テーブルの詳細は、"InterSystems Business Intelligence のモデルの定義" の "ファクト・テーブルおよびディメンジョン・テーブルの詳細" を参照してください。)以下に例を示します。
ClassMethod %OnGetFilterMembers(pFilter As %String, Output pMembers As %List, pSearchKey As %String = "") As %Status
{
set status = $$$OK
try {
if (pFilter = "AgeGroup") {
//get values from level table
set sql = "SELECT DISTINCT DxAgeGroup FROM BI_Model_PatientsCube.DxAgeGroup"
set stmt = ##class(%SQL.Statement).%New()
set status = stmt.%Prepare(sql)
if $$$ISERR(status) {write "%Prepare failed:" do $SYSTEM.Status.DisplayError(status) quit}
set rs = stmt.%Execute()
if (rs.%SQLCODE '= 0) {write "%Execute failed:", !, "SQLCODE ", rs.%SQLCODE, ": ", rs.%Message quit}
while(rs.%Next()) {
set display=rs.DxAgeGroup
set actual="&["_display_"]"
set pMembers($I(pMembers)) = $LB(display,actual)
}
if (rs.%SQLCODE < 0) {write "%Next failed:", !, "SQLCODE ", rs.%SQLCODE, ": ", rs.%Message quit}
}
}
catch(ex) {
set status = ex.AsStatus()
}
quit status
}
この例では pSearchKey 引数を使用しません。
MDX クエリを変更してフィルタ値を使用する
MDX ベースの KPI では、クエリを変更してフィルタを使用するには、%OnGetMDX() メソッドを実装します。スタジオで KPI ウィザードを使用して、ソース・タイプとして MDX を選択する場合、生成される KPI クラスには、このメソッドの以下のスタブ定義が含まれます。これを開始点として使用できます。
/// Return an MDX statement to execute.
Method %OnGetMDX(ByRef pMDX As %String) As %Status
{
Quit $$$OK
}
変数 pMDX には、<kpi> の mdx 属性で指定される MDX クエリが格納されます(この属性を指定しなかった場合、pMDX は Null になります)。
このメソッドを実装する場合、以下の手順を実行します。
-
初期クエリがない場合、変数 pMDX の初期値を指定します。これは MDX SELECT クエリです。
"基本的な KPI の定義" で説明したように、mdx 属性でクエリを指定しない場合、初期クエリはありません。
-
該当するフィルタそれぞれを調べ、その値を取得します。
このためには、最初のサブセクションで説明したように、KPI インスタンスの %filterValues プロパティを使用します。
-
各フィルタ値を解析し、必要に応じて、MDX %FILTER 節で使用できる形式に変換します (これがフィルタを使用する方法の場合)。適切な形式をリストするテーブルは、2 番目のサブセクションを参照してください。
-
ニーズに合わせて、変数 pMDX を変更して、フィルタ値を使用します。最も一般的な状況では、以下のように NULL でない各フィルタに %FILTER 節を追加します。
%FILTER mdx_expression
ここで、mdx_expression は、前の手順で作成した、そのフィルタの式です。
または、式を結合する MDX タプル式を作成し、以下のように 1 つの %FILTER 節を追加します。
%FILTER tuple_expression
一般的ではない状況では、フィルタ値を使用して、別の方法でクエリ文字列を書き換えることができます。
-
$$$OK (または 1) を返します。
最後のサブセクションに例を示します。
フィルタ値へのアクセス
ユーザがフィルタ項目を選択すると、KPI インスタンスの %filterValues プロパティが設定されます。このプロパティは、システムによって以下のように作成されたオブジェクト (具体的には %ZEN.proxyObjectOpens in a new tab のインスタンス) です。
-
KPI のフィルタごとに、フィルタと同じ名前 (大文字と小文字が区別されます) のプロパティが 1 つあります。
例えば、KPI に filter1、filter2、および filter3 という名前のフィルタがある場合、KPI インスタンスの %filterValues プロパティには filter1、filter2、および filter3 という名前のプロパティがあります。
-
%filterValues のプロパティには、以下のテーブルに示す値が含まれます。
ユーザがフィルタで選択する対象 |
%filterValues.FilterName の値 |
留意事項 |
なし |
null |
|
1 つの項目 |
item |
|
複数の項目 |
{item1,item2} |
複数選択がオフの場合には該当なし |
1 つの項目と [除外] オプション |
%NOT item |
複数選択がオフの場合には該当なし |
複数の項目と [除外] オプション |
%NOT {item1,item2} |
複数選択がオフの場合には該当なし |
範囲 |
item1:item2 |
ピボット・テーブルで定義されるフィルタに対してのみ適用され、KPI に影響します |
%FILTER で使用するためにフィルタ値を MDX 式に変換
以下のテーブルは、ユーザの選択に応じて、%FILTER 節での使用に適切な MDX 式をリストしています。
ユーザがフィルタで選択する対象 |
該当する MDX %FILTER 式 |
なし |
none (この場合、%FILTER 節を適用しません) |
1 つの項目 |
[dimension].[hierarchy].[level].[member] |
1 つの項目と [除外] オプション |
[dimension].[hierarchy].[level].[member].%NOT |
item1 および item2 |
{item1,item2,...} (各 item の形式は [dimension].[hierarchy].[level].[member]) |
複数の項目と [除外] オプション |
EXCEPT([dimension].[hierarchy].[level].MEMBERS,{item,item,item,...}) (各 item の形式は [dimension].[hierarchy].[level].[member]) |
範囲 |
[dimension].[hierarchy].[level].[member]:[member] |
使用例は、サンプル・クラス BI.Utils.MDXAutoFiltersKPI のメソッド BuildString() を参照してください。
複数選択が無効になっている場合、EXCLUDE も無効になり、フィルタ値の使用できる形式が減ることに注意してください。この場合、クエリ構造は比較的単純です。
例
%OnGetMDX() の以下の実装は、複数選択が無効になっている KPI に適用されます。
Method %OnGetMDX(ByRef pMDX As %String) As %Status
{
if (..%filterValues."[aged].[h1].[age group]"'="")
{
set pMDX = pMDX _ " %FILTER [aged].[h1].[age group]." _..%filterValues."[aged].[h1].[age group]"
}
if (..%filterValues."[gend].[h1].[gender]"'="")
{
set pMDX = pMDX _ " %FILTER [gend].[h1].[gender]." _..%filterValues."[gend].[h1].[gender]"
}
if (..%filterValues."[homed].[h1].[zip]"'="")
{
set pMDX = pMDX _ " %FILTER [homed].[h1].[zip]." _..%filterValues."[homed].[h1].[zip]"
}
quit $$$OK
}
このメソッドは、区切りプロパティ名を使用しているため、読みにくい場合があります。メモ :
SQL クエリを変更してフィルタ値を使用する
SQL ベースの KPI では、クエリを変更してフィルタを使用するには、%OnGetSQL() メソッドを実装します。スタジオで KPI ウィザードを使用して、ソース・タイプとして SQL を選択する場合、生成される KPI クラスには、このメソッドの以下のスタブ定義が含まれます。これを開始点として使用できます。
/// Return an SQL statement to execute.
Method %OnGetSQL(ByRef pSQL As %String) As %Status
{
Quit $$$OK
}
変数 pSQL には、<kpi> の sql 属性で指定される SQL クエリが格納されますこの属性を使用していない場合、pSQL は Null です。
このメソッドを実装する場合、以下の手順を実行します。
-
初期クエリがない場合、変数 pSQL の初期値を指定します。これは SQL SELECT クエリです。
"基本的な KPI の定義" で説明したように、sql 属性でクエリを指定しない場合、初期クエリはありません。
-
該当するフィルタそれぞれを調べ、その値を取得します。このオプションは以下のとおりです。
-
ニーズに合わせて、変数 pSQL を変更して、フィルタ値を使用します。最も一般的な状況では、クエリを変更して SQL WHERE 節を組み込みます。
一般的ではない状況では、フィルタ値を使用して、別の方法でクエリ文字列を書き換えることができます。
2 番目および 3 番目のサブセクションに例を示します。
-
$$$OK (または 1) を返します。
Note:
SQL ベースの KPI は 1000 行を超えることはできません。返される行数は自動的に制限されます。
%GetSQLForFilter()
SQL ベースの KPI では、クエリに組み込むのに便利な形式でフィルタ値にアクセスするメソッドを使用できます。
method %GetSQLForFilter(sql_field_reference,filter_name) As %String
現在のフィルタ選択を調べて、SQL クエリの WHERE 節で使用できる文字列を返します。
sql_field_expression は SQL フィールド名で、矢印構文を含むことができます。filter_name は、この KPI で定義されるフィルタの名前です。
例えば、以下のメソッド呼び出しを考えてみます。
..%GetSQLForFilter("City->Name","City")
以下のテーブルに、さまざまなシナリオでこのメソッド呼び出しによって返される値を示します。
シナリオ |
メソッドによって返される値 |
ユーザが PINE を選択する |
City->Name = 'PINE' |
ユーザが MAGNOLIA で始まり PINE で終わる範囲を選択する |
City->Name = ('MAGNOLIA':''PINE') |
ユーザが MAGNOLIA と PINE を選択する |
City->Name IN ("MAGNOLIA','PINE') |
ユーザが PINE を選択して [除外] を選択する |
City->Name <> 'PINE' |
ユーザが MAGNOLIA と PINE を選択して [除外] を選択する |
City->Name NOT IN ('MAGNOLIA','PINE') |
SQL KPI の例 1
以下の例は、サンプル・クラス BI.Model.KPIs.DemoSQL のものです。この場合、フィルタは、GROUP BY 節と ORDER BY 節を SQL クエリに追加します。
Method %OnGetSQL(ByRef pSQL As %String) As %Status
{
//this is the start of the SQL query for this KPI
Set pSQL = "SELECT Count(*),AVG(Age) FROM BI_Study.Patient "
Set where = ""
//look at %filterValues to see if a filter has been applied to this KPI instance
If $IsObject(..%filterValues) {
If (..%filterValues.ZipCode'="")
{
// Call utility method that returns filter data in convenient format
Set sqlstring=..%GetSQLForFilter("HomeCity->PostalCode","ZipCode")
Set where = "WHERE "_sqlstring
}
}
Set groupby="GROUP BY HomeCity "
Set orderby="ORDER BY HomeCity "
// assemble the SQL statement
Set pSQL=pSQL_where_groupby_orderby
Quit $$$OK
}
SQL KPI の例 2
以下の例は、サンプル・クラス HoleFoods.KPISQL のものです。
Method %OnGetSQL(ByRef pSQL As %String) As %Status
{
If $IsObject(..%filterValues) {
Set tWHERE = ""
If (..%filterValues.City'="") {
Set tWHERE = tWHERE _ $S(tWHERE="":"",1:" AND ") _ " Outlet->City = '" _ ..%filterValues.City _"'"
}
If (..%filterValues.Product'="") {
Set tWHERE = tWHERE _ $S(tWHERE="":"",1:" AND ") _ " Product = '" _ ..%filterValues.Product _"'"
}
If (tWHERE'="") {
// insert WHERE clase within query
Set tSQL1 = $P(pSQL,"GROUP BY",1)
Set tSQL2 = $P(pSQL,"GROUP BY",2)
Set pSQL = tSQL1 _ " WHERE " _ tWHERE
If (tSQL2 '= "") {
Set pSQL = pSQL _ " GROUP BY" _ tSQL2
}
}
}
Quit $$$OK
}
この場合、KPI は、"基本的な KPI の定義" で説明したように、sql 属性内に初期クエリを定義します。%OnGetSQL() メソッドは、そのクエリを変更します。
その他の MDX KPI の例
このセクションでは、その他の MDX KPI の例について説明します。
DemoMDXAutoFilters KPI
サンプル・クラス BI.Model.KPIs.DemoMDXAutoFilters の KPI は単純ですが、特別なスーパークラスを使用します。
Class BI.Model.KPIs.DemoMDXAutoFilters Extends BI.Utils.MDXAutoFiltersKPI
{
Parameter CUBE = "PATIENTS";
Parameter DOMAIN = "PATIENTSAMPLE";
XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
{
<kpi name="DemoMDXAutoFilters" displayName="DemoMDXAutoFilters"
sourceType="mdx"
mdx="SELECT {[Measures].[%COUNT],[Measures].[Avg Age],[Measures].[Avg Allergy Count]} ON 0,
NON EMPTY [DiagD].[H1].[Diagnoses].Members ON 1 FROM [Patients]">
<property name="Patient Count" displayName="Patient Count" columnNo="1" />
<property name="Avg Age" displayName="Avg Age" columnNo="2" />
<property name="Avg Allergy Count" displayName="Avg Allergy Count" columnNo="3" />
</kpi>
}
}
このクラスは、直接フィルタを定義することも、直接フィルタ・メンバを定義することもなく、ハードコードされた MDX クエリのみを定義していることに注意してください。ただし、この KPI のテスト・ページを表示した場合、Patients キューブのすべてのレベルをフィルタとして使用でき、KPI は適切な %WHERE 節をクエリに追加します。以下に例を示します。
この KPI は、サンプル BI.Utils.MDXAutoFiltersKPI を拡張します。これは、フィルタを定義し、クエリを書き換えます。
このクラスには、以下のメソッドが存在します。
-
%OnGetFilterList() は、CUBE クラス・パラメータで指定されたキューブに定義されているすべてのレベルを取得します。
-
%OnGetFilterMembers() が実装されています。各レベルで、ピボット・テーブルで要求される形式で、レベル・メンバを取得します。このページで前述した "ピボット・テーブルのフィルタ構文" を参照してください。
-
インスタンス・メソッド FilterBuilder() は、キューブ・ベースのフィルタを繰り返し処理して、それぞれの現在の値を取得し、それらを結合して MDX %FILTER 節としての使用に適した 1 つの文字列を生成します。
-
%OnGetMDX() は、ハードコードされたクエリに %FILTER 節を追加します。
DemoInteroperability KPI
サンプル・クラス BI.Model.KPIs.DemoInteroperability の KPI は、前述の例より複雑です。このクラス内で、%OnGetFilterList() は、CUBE クラス・パラメータで指定されたキューブに定義されているすべてのレベルを取得します。次に、Yaxis という名前の別のフィルタを追加します。
ClassMethod %OnGetFilterList(ByRef pFilters As %List, pDataSourceName As %String = "") As %Status
{
//call method in superclass so we can get filters of the associated cube
set tSC=##super(.pFilters,pDataSourceName)
quit:$$$ISERR(tSC) tSC
//update pFilters array to include the custom filter
set pFilters($i(pFilters)) = $lb("Yaxis","Yaxis",,0)
quit $$$OK
}
%OnGetFilterMembers() が実装されています。フィルタ Yaxis の場合、このメソッドはメンバ・セットを提供します。他のフィルタの場合、ピボット・テーブルで要求される形式で、レベル・メンバを取得します。このページで前述した "ピボット・テーブルのフィルタ構文" を参照してください。このメソッドは、以下のとおりです。
ClassMethod %OnGetFilterMembers(pFilter As %String, Output pMembers As %List, pSearchKey As %String = "",
pDataSourceName As %String = "") As %Status
{
set pMembers=""
if (pFilter="Yaxis") {
set pMembers($I(pMembers))=$LB("Home City","[homed].[h1].[city]")
set pMembers($I(pMembers))=$LB("Favorite Color","[colord].[h1].[favorite color]")
set pMembers($I(pMembers))=$LB("Profession","[profd].[h1].[profession]")
set pMembers($I(pMembers))=$LB("Diagnoses","[diagd].[h1].[diagnoses]")
} else {
//call method in superclass so we can get filter members for the associated cube
do ..%GetMembersForFilter(..#CUBE,pFilter,.pMembers)
}
quit $$$OK
}
最後に、%OnGetMDX() は MDX クエリを構築します。Yaxis フィルタは、行に使用するレベルを決定します。このメソッドは、%FILTER 節をクエリに追加します。%FILTER 節は、前の例と同様に、キューブ・ベースの任意のフィルタを使用します。
Method %OnGetMDX(ByRef pMDX As %String) As %Status
{
set yaxis=", NON EMPTY [profd].[h1].[profession].MEMBERS ON 1"
//check custom filter value
if (..%filterValues."Yaxis"'="") {
set yaxis=", NON EMPTY "_..%filterValues.Yaxis_".MEMBERS ON 1"
}
set pMDX="SELECT {MEASURES.[%COUNT],MEASURES.[avg age]} on 0"_yaxis_" FROM "_..#CUBE
/// append a %FILTER clause to handle any other filter values
Set pMDX = pMDX _ ..FilterBuilder()
Quit $$$OK
}
KPI のリストの定義
リスト・オプションを含むように KPI を定義できます。この場合、KPI にフィルタも含まれる場合、リスト定義でフィルタ選択を考慮する必要があります。
リストを定義するために、KPI クラスに %OnGetListingSQL() メソッドを実装します。このメソッドには、以下のシグニチャがあります。
ClassMethod %OnGetListingSQL(ByRef pFilters As %String, ByRef pSelection As %String) As %String
このメソッドは、リスト・クエリのテキストを返します。引数は以下のとおりです。
-
pFilters は、現在のフィルタ値を格納する多次元配列です。この配列には以下のノードがあります。
ノード |
ノード値 |
pFilters(filter_name)。filter_name は、この KPI で定義されるフィルタの名前です。 |
このフィルタの現在の値 |
詳細は、"KPI フィルタの定義" を参照してください。
-
pSelection は、現在の選択に関する情報を格納する多次元配列です。この配列には以下のノードがあります。
ノード |
ノード値 |
pSelection("selectedRange") |
ピボットで形式 "startRow,startCol,endRow,endCol" (1-based) の文字列として現在選択されているセル。 |
pSelection("rowValues") |
選択された行の値のコンマ区切りのリスト。これらの値では、コンマが円記号 (\) として表示されます。KPI のプロパティでこの値が構成されていない場合は、このノードには代わりに系列名が含まれます。 |
pSelection("sortColumn") |
リストの並べ替えに使用する列の番号を指定します。0 を使用すると並べ替えは行われません。 |
pSelection("sortDir") |
並べ替えの方向を "ASC" または "DESC" で指定します。 |
このメソッドは、SQL SELECT クエリを返す必要があります。このクエリでは、他のリストと同様に、矢印構文および SQL 関数も使用できます。
または、%OnGetListingResultSet() メソッドをオーバーライドできます。オーバーライドする場合は、結果セットを作成して実行する必要があります。
例
以下の例は、HoleFoods.KPISQL からの抜粋です。
ClassMethod %OnGetListingSQL(ByRef pFilters As %String, ByRef pSelection As %String) As %String
{
Set tSQL = "SELECT TOP 1000 %ID,DateOfSale,Product FROM HoleFoods.SalesTransaction"
// apply sorting, if asked for
If (+$G(pSelection("sortColumn"))>0) {
Set tSQL = tSQL _ " ORDER BY " _ pSelection("sortColumn") _ " " _ $G(pSelection("sortDir"))
}
Quit tSQL
}
FeedbackOpens in a new tab