On-demand App Generation(ODAG) in QlikSense

ODAG 简介

On-demand App译为:按需生成应用程序 以下用 ODAG 简称,ODAG使分析人员能够在 Qlik Sense 中加载和分析大数据源。

使用ODAG需要两个App:

  • Selection App(选择/筛选应用程序)
  • Template App(模板应用程序)

且在创建他们时,需要一些特殊的脚本代码!

在QMC中启用按需应用服务

在开始编写 ODAG 脚本之前,我们需要在 QMC 中启用按需应用服务,如下所示。

1、在On-demand App Service选项下启用ODAG服务。

2、默认情况下,我们需要通过单击复选框启用它。

ODAG 程序脚本

  1. 按需功能包含两个名为 “Selection App” 和 “Template App” 的应用程序。
  2. ODAG 必须以适度的维度粒度加载数据。
  3. ODAG 包含带有数据绑定表达式的加载脚本,用于表示对数据源进行的查询。
  4. ODAG 可以链接到多个Template App,单个Template App可以链接到多个Selection App

注意
Template App 的数据绑定表达式必须与链接到它的 Selection App 中的字段相对应。

Selection App脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
ODBC Connect to '<your_db_link>';

FactTable:
Load
PURCHASEDATE as [Purchase Date]
PRODUCTID as Product,
STORENAME as [Store Name],
STOREDESCRIPTION as [Store Description],
PRICE as Price,
TAX as Tax,
// total_lines用来生成返回记录行数
1 as TOTAL_LINES
;
sql select
to_chat(pp.purchasedate,'DD/MM/YYYY') as purchasedate,
pp.productid,
s.storename,
s.storedescription,
Sum(pp.price) as price,
Sum(pp.tax) as tax
from product_Price pp inner join store s
on s.storeid = pp.storeid
Group by pp.productid, s.storename, s.storedescription;

Left Keep(FactTable)

DimensionTable:
Load
PRODUCTID as Product,
PRODUCTYTPE as [Product Type],
PRODUCTDESCRIPTION as [Product Description],
CUSTOMERNAME as [Customer Name],
CUSTOMERADDRESS as [Customer Address]
;

sql select
p.productid,
p.producttype,
c.productdescription,
ct.customername,
ct.customeraddress
from product_account p
inner join product_company c
on c.productcompanyid = a.productcompanyid
inner join product_customer_type ct
on ct.productcustomertypeid = a.productcustomertypeid;

2. Template App 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// 为维度表中的字段创建子例程  
SUB ExtendWhere(Name, ValVarName)
LET T = Name & '_COLNAME';
LET ColName = $(T);
LET Values = $(ValVarName);
IF len(Values) > 0 THEN
IF len(WHERE_PART) > 0 THEN
LET WHERE_PART = '$(WHERE_PART) AND $(ColName) IN ( $(Values) )';
ELSE
LET WHERE_PART = ' WHERE $(ColName) IN ( $(Values) )';
ENDIF
ENDIF
END SUB;

SET PRODUCTYTPE = ;

// 右侧字段应该与Load字段匹配
SET PRODUCTYTPE = $(ods_Product Type);

// 右侧字段应与数据库字段匹配
SET PRODUCTYTPE_COLNAME='p.producttype';
SET CUSTOMERNAME = ;

// 右侧字段应该与Load字段匹配
SET CUSTOMERNAME = $(ods_Customer Name);

// 右侧字段应与数据库字段匹配
SET CUSTOMERNAME_COLNAME='ct.customername';

SET WHERE_PART = '';

FOR EACH fldname IN 'PRODUCTYTPE', 'CUSTOMERNAME'
LET vallist = $($(fldname));
WHEN (IsNull(vallist)) LET vallist = '';
IF len(vallist) > 0 THEN
CALL ExtendWhere('$(fldname)','vallist');
ENDIF
NEXT fldname

TRACE Generated WHERE clause: ;
TRACE $(WHERE_PART);

//Date字段创建自定义子例程
SUB ExtendWhere1(Name, ValVarName)
LET T = Name & '_COLNAME';
LET ColName = $(T);
LET Values = $(ValVarName);
IF len(Values) > 0 THEN
IF len(WHERE_PART1) > 0 THEN
LET WHERE_PART1 = '$(WHERE_PART1) AND ( $(Values) )';
ELSE
LET WHERE_PART1 = ' $(Values) ';
ENDIF
ENDIF
END SUB;

//在加载左侧PURCHASEDATE中提到了第一、第二和第三组变量名
SET PURCHASEDATE = ;  

// SET 语句右侧 $() 中的字段必须与 from selection app 中的字段匹配 
SET PURCHASEDATE = $(ods_Purchase Date);  
SET PURCHASEDATE_COLNAME = 'PURCHASEDATE';
SET WHERE_PART1 = '';

/*
* 首先设置语句变量字段 PURCHASEDATE 需要在
* For 循环中提到 FOR EACH fldname IN 'PURCHASEDATE'
*/
LET vallist = $($(fldname));
WHEN (IsNull(vallist)) LET vallist = '';
IF len(vallist) > 0 THEN
CALL ExtendWhere1('$(fldname)','vallist');
ENDIF
NEXT fldname;

TRACE Generated WHERE clause: ;
TRACE $(WHERE_PART1);

// 为FactTable中的其他字段创建子例程
SUB ExtendWhere2(Name, ValVarName)
LET T = Name & '_COLNAME';
LET ColName = $(T);
LET Values = $(ValVarName);
IF len(Values) > 0 THEN
   IF len(WHERE_PART2) > 0 THEN
 LET WHERE_PART2 = '$(WHERE_PART2) AND $(ColName) IN ( $(Values) )';
   ELSE
 LET WHERE_PART2 = ' WHERE $(ColName) IN ( $(Values) )';
   ENDIF
ENDIF
END SUB;

SET PRODUCTID =;

// 右侧字段应该与Load -UI字段匹配  
SET PRODUCTID= $(ods_Product);

// 右侧字段应与数据库字段匹配
SET PRODUCTID_COLNAME='pp.productid';
SET STORENAME =;

// 右侧字段应该与Load -UI字段匹配
SET STORENAME = $(ods_Store Name);

// 右侧字段应与数据库字段匹配
SET STORENAME _COLNAME='s.storename';
SET PRICE =;

// 右侧字段应该与Load -UI字段匹配
SET PRICE = $(ods_Price);

// 右侧字段应与数据库字段匹配
SET PRICE_COLNAME='pp.price';
SET WHERE_PART2 = '';

FOR EACH fldname IN 'PRODUCTID ', 'STORENAME ', 'PRICE'
LET vallist = $($(fldname));
WHEN (IsNull(vallist)) LET vallist = '';
IF len(vallist) > 0 THEN
CALL ExtendWhere2('$(fldname)','vallist');
ENDIF
NEXT fldname

TRACE Generated WHERE clause: ;
TRACE $(WHERE_PART2);

ODBC Connect to '<your_db_link>';

FactTable:
Load
PURCHASEDATE as [Purchase Date]
PRODUCTID as Product,
STORENAME as [Store Name],
STOREDESCRIPTION as [Store Description],
PRICE as Price,
TAX as Tax,
1 as TOTAL_LINES
;
sql select
to_chat(pp.purchasedate,'DD/MM/YYYY') as purchasedate,
pp.productid,
s.storename,
s.storedescription,
Sum(pp.price) as price,
Sum(pp.tax) as tax
from product_Price pp inner join store s
on s.storeid = pp.storeid $(WHERE_PART2)
and pp.purchasedate <= to_Date($(WHERE_PART1),'DD/MM/YYYY');                                               

Left Keep(FactTable)

DimensionTable:
Load
PRODUCTID as Product,
PRODUCTYTPE as [Product Type],
PRODUCTDESCRIPTION as [Product Description],
CUSTOMERNAME as [Customer Name],
CUSTOMERADDRESS as [Customer Address]
;
sql select
p.productid,
p.producttype,
c.productdescription,
ct.customername,
ct.customeraddress
from product_account p inner join product_company c
on c.productcompanyid = a.productcompanyid
inner join product_customer_type ct
on ct.productcustomertypeid = a.productcustomertypeid $(WHERE_PART);

注意:
无需重新加载Template App只需对其进行建模。
通过生成新的应用程序为所选值重新加载我们的Template App。

配置关联

通过生成新的应用程序为所选值重新加载我们的 Template App。

在 Selection App 和 Template App 之间创建“应用程序导航链接”。

  1. 打开 Selection App 并选择“编辑”。
  2. 从左侧面板中选择应用程序导航链接。
  3. 单击“创建新”按钮以打开“创建新的应用程序导航链接”对话框。
  4. 根据你的意愿命名新的按需应用程序导航链接
  5. 从下拉列表中选择 Template App
  6. 编写一个表达式来计算详细记录的总数,即我们在上面的脚本中创建的 SUM(TOTAL_LINES)
  7. 指定最大行数。

注意:
最大行数应小于或等于SUM(TOTAL_LINES)

  1. 计数指定最大生成的应用程序数。
  2. 在生成的应用程序菜单的保留时间右侧的下拉菜单中,选择保留期的时间单位。保留时间的选项为小时,天或永不过期。
  3. 在“打开生成的应用程序菜单的默认视图”中,选择在打开从导航链接生成的应用程序时首先显示的工作表。
  4. 从选择应用程序中选择其中一个工作表,从中创建导航链接。
  5. 然后在ODAG过滤器上进行选择,当 ODAG2 按钮变为绿色时,用户就可以生成应用程序。

On-demand App Generation(ODAG) in QlikSense
https://blog.pangcy.cn/2019/05/07/数据库相关/QlikSense/On-demand App Generation(ODAG) in QlikSense/
作者
子洋
发布于
2019年5月7日
许可协议