使用变量

2021-6-29 About 18 min

# 使用变量

# 支持使用变量场景列表

  • 数据集查询定义
  • 数据集维度可选值查询
  • 看板参数
    • 通用过滤器输入值
    • 下拉框默认值
  • 权限模板查询语句
  • 大屏静态组件Query方式获取数据查询
  • 大屏静态组件API方式获取数据URL地址
  • 大屏静态文本超链地址
  • 大屏图标超链地址

# 变量的产生

# 内置变量

变量名 解释
${loginName} 用户账号: "admin"
${userName} 用户名:"超级管理员"

# 内置日期变量

内置日期工具cdt,具体使用方法如下:

# 日期操作

第一个参数用cdt动态生成需要的日期,第二个参数指定日期格式化

-- 当前日期 ${cdt.now(), "yyyy-MM-dd"}  
-- 增加一小时 ${cdt.addHour(1), "yyyy-MM-dd"}  
-- 增加一天 ${cdt.addDay(1), "yyyy-MM-dd"}  
-- 增加一月 ${cdt.addMonth(1), "yyyy-MM-dd"} 
-- 增加一周 ${cdt.addWeek(1), "yyyy-MM-dd"} 
-- 增加一年 ${cdt.addYear(1), "yyyy-MM-dd"}
1
2
3
4
5
6
${}内部使用使用单参数,利用cdt提供的格式换参数format
-- 增加一小时 ${cdt.addHour(1, "yyyy-MM-dd")}  
-- 增加一天 ${cdt.addDay(1, "yyyy-MM-dd")}  
-- 增加一月 ${cdt.addMonth(1, "yyyy-MM-dd")} 
-- 增加一周 ${cdt.addWeek(1, "yyyy-MM-dd")} 
-- 增加一年 ${cdt.addYear(1, "yyyy-MM-dd")}
1
2
3
4
5
6

# 指定日期操作

你也可以对指定日期进行操作,

-- 增加一天 ${cdt.addDay("2021-10-30",1, "yyyy-MM-dd")}  
-- 增加一月 ${cdt.addMonth("2021-10-30",1, "yyyy-MM-dd")} 
-- 增加一周 ${cdt.addWeek("2021-10-30",1, "yyyy-MM-dd")} 
-- 增加一年 ${cdt.addYear("2021-10-30",1, "yyyy-MM-dd")}
1
2
3
4

指定日期第一个日期参数支持的日期格式

yyyy/MM/dd HH:mm:ss
yyyy.MM.dd HH:mm:ss
yyyy年MM月dd日 HH时mm分ss秒
yyyy-MM-dd
yyyy/MM/dd
yyyy.MM.dd
HH:mm:ss
HH时mm分ss秒
yyyy-MM-dd HH:mm
yyyy-MM-dd HH:mm:ss.SSS
yyyyMMddHHmmss
yyyyMMddHHmmssSSS
yyyyMMdd
EEE, dd MMM yyyy HH:mm:ss z
EEE MMM dd HH:mm:ss zzz yyyy
yyyy-MM-dd'T'HH:mm:ss'Z'
yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
yyyy-MM-dd'T'HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss.SSSZ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 日期变量支持的起始周期计算

# 指定日期(日期参数类型为日期)对应的年份第一天,格式化为yyyy-MM-dd 
${cdt.startOfYear(cdt.addDay(-1), "yyyy-MM-dd")}  
# 指定日期(日期参数类型为字符串)对应的年份第一天,格式化为yyyy-MM-dd 
${cdt.startOfYear("2023-08-11", "yyyy-MM-dd")}  

-- 年份第一天 ${cdt.endOfYear(date, "yyyy-MM-dd")}  
-- 年份最后一天 ${cdt.endOfYear(date, "yyyy-MM-dd")}  
-- 季度第一天 ${cdt.startOfQuarter(date, "yyyy-MM-dd")}  
-- 季度最后一天 ${cdt.endOfQuarter(date, "yyyy-MM-dd")}  
-- 月度第一天 ${cdt.startOfMonth(date, "yyyy-MM-dd")}  
-- 月度最后一天 ${cdt.endOfMonth(date, "yyyy-MM-dd")}  
-- 周第一天 ${cdt.startOfWeek(date, "yyyy-MM-dd")}  
-- 周最后一天 ${cdt.endOfWeek(date, "yyyy-MM-dd")}  
1
2
3
4
5
6
7
8
9
10
11
12
13

# 计算日期差

cdt.between("2021-10-30", "2021-11-30", "day")
cdt.between("2021-10-30", "2021-11-30", "hour")
cdt.between("2021-10-30", "2021-11-30", "minute")
1
2
3

提示

因为年、月属于不固定时间长度单位所以无法计算时间差

# 看板参数关联到环境变量

# 图表联动关联到环境变量

# URL参数传递变量

可以通过url参数设定变量所有的url参数都会解析为环境变量, 做看板集成的时候尤为有用

http://localhost:8088/?up=aa&a=%E6%B5%8B%E8%AF%95#/config/cockpit/200326104201751
1

# 多看板集成-全局变量

url里面的参数为全局参数,在多看板集成场景下会被所有看板继承
http://localhost:8088/render-html.html?a=aa&country=USA
1
2

# 多看板集成-局部变量

  • 局部变量可以覆盖全局变量
  • 局部变量为对象
boards=encodeURIComponent(JSON.stringify(
[
    {
        showParams: true,
        title: '第一个看板',
        boardId: 63,
        hiddenParamNames: [],
        filters: {"boardParams":[{"id":"5chiv3mmalw","name":"国家","type":"=","values":[]}]},
        variables: { //这个变量只针对boardId 63
          country: 'Mexico'
        }
    },
    {
        showParams: true,
        title: '第二个看板',
        boardId: 64,
        hiddenParamNames: ['国家4', '国家3'],
    }
]
))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 变量的使用

# 数据集中/或者即席查询中

.... 省略其他查询脚本 ...
  JOIN foodmart.region r ON c.REGION_ID = r.REGION_ID
  JOIN foodmart.customer d ON a.CUSTOMER_ID = d.CUSTOMER_ID
WHERE r.sales_country = '${country}'
1
2
3
4

# 变量默认值

上面的查询语句中直接使用了自定义变量,但是BI系统如果没有自己在url中传参实际上会出现空值,所以需要给变量一个默认值,让查询在没有传参的场景也能正常运行

.... 省略其他查询脚本 ...
  JOIN foodmart.region r ON c.REGION_ID = r.REGION_ID
  JOIN foodmart.customer d ON a.CUSTOMER_ID = d.CUSTOMER_ID
WHERE r.sales_country = '${country!"USA"}'
1
2
3
4

# 数组变量

# 获取数组变量中的第N个值

当关联到环境变量的参数为数组或者被赋予多个值时,可以通过内置数组udf获取数组中某个元素值,

${arr.get(variable, nth, “defaultValue”)}
或者 ${arr.get(variable, nth) ! “defaultValue”}

小技巧

arr.get函数的第一个变量可以为非数组,arr.get("a", 0) 返回值依旧为"a", arr.get("a", 1)为空白

比如现在把日期范围关联到环境变量dt,在查询中可以这样取值

select
       ....
  from 
 where date_columen between 
             '${arr.get(dt, 0) ! cdt.addDay(-10,"yyyy-MM-dd")}' 
         and '${arr.get(dt, 1) ! cdt.addDay(-1,"yyyy-MM-dd")}'
1
2
3
4
5
6

也可以用下面的方式在变量没有初始化的情况下设置默认值

${arr.get(dt, 0, cdt.addDay(-1,"yyyy-MM-dd")) }
1

# 连接数组变量

${arr.joinString(variable, ”defaultValues")}
${arr.joinNumber(variable, “defaultValues")}

WHERE SALES_COUNTRY IS NOT NULL
   AND r.sales_country in  (${arr.joinString(country, “USA, Mexico")})
   AND b.month_of_year in (${arr.joinNumber(month, "1, 2, 3,")})

--->输出
WHERE SALES_COUNTRY IS NOT NULL
   AND r.sales_country in  ('USA', 'Mexico')
   AND b.month_of_year in (1, 2, 3) 
1
2
3
4
5
6
7
8

# 案例

# 逻辑脚本,判断是否存储变量

<%
  var  where = "where 1 = 1";
  if (has(township)) {
      where = where + (" AND township = '" + township + "'");
  }
  if (has(village)) {
      where = where + (" AND village = '" + village + "'");
  }
  if (has(group_name)) {
      where = where + (" AND group_name = '" + group_name + "'");
  }
%>
select *,1 as cnt from pas_wm_dz_wt ${where}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 查询模板整体替换

判断某个变量是否存在(有值),然后整体替换查询sql,注意的是两个不同的sql需要保证输出的字段一致

<%
  var sql;
  if (has(country)) {
      sql = 'select 1 as c';
  } else {
      sql = 'select 2 as c';
  }
%>

${sql}
1
2
3
4
5
6
7
8
9
10

# 日期处理

技巧

在<% %>界定符中,通过println函数打印的值会最终输出结果中,可以通过println内容带注释符号,调试模板语法是否正确 println("-- [Log] " + result);

<%
  var months = strutil.split(month!"2021-02-01", ",");
  var m2 = cdt.add("2021-02-01", 2, -1, "yyyy-MM-dd");
  var result = '';
  for(m in months){
      var monthStr = cdt.addMonth(m, -1, "yyyy-MM-dd");
      if (isEmpty(result)) {
          result = monthStr;
      }
      println("-- [Log] " + result);
      result = result + ", " + monthStr;
  }
%>

select 1 as c

-- ${month}
-- ${result}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Side Effect 副作用

  • 对于需要缓存的离线数据集,由于缓存的key为变量赋值之后真实执行查询的语句,当有变量存在的时候会把原来一个数据集保存的数据替换为所有不同变量对应的查询分别缓存;
  • 原本执行一次查询,缓存一次,多次读写的数据集需要多次查询、写缓存,可能造成一定的用户体验上高延迟负面影响;
  • 变量数据集更加适用于不需要缓存的数据源聚合;

IBI的模板引擎采用Beetl (opens new window), 更多高级用法可以查阅该引擎相关文档 (opens new window)

Last update: August 15, 2023 10:27