Saiku部分函数解析与默认添加日期限制查詢
Saiku函数解析
now() : 获取当前日期
IIF(logic_exp, string, string): IIF判断,logic_exp是逻辑表达式,结果为true/false , 为true的时候取第二个参数值,为false的时候取第三个参数值。 eg: IIF(1>2,"1大于2","1不大于2") , 结果为 1不大于2
year(Date) : 获取日期的年份信息 eg: YEAR(cdate("2019-02-26"))
CDate(String) : 将String类型的数据转换为日期类型 eg: CDate("2019-02-26")
STR( numeric): 将数据类型转换为String类型 eg: STR(55.6)
DateDiff(String, Date, Date) : 得到日期相减的值,第一个参数表示interval,第二个参数是日期类型,第三个是日期类型, eg: datediff("y", CDate("2019-02-26"), CDate("2019-02-25")) 结算逻辑为 得出2019-02-26至 2019-02-25中相差的天数,结果为 1 。
interval的取值如下:
Saiku查询设定:Saiku查询数据时,每次都是全量查询的,我们现在需要默认展示近一周的数据。
实现默认查询一周数据方案一:使用MDX表达式
通过编写MDX表达式,添加新的指标信息对一周以内的数据进行标识 (其实我也想添加新的维度信息,但是好像不生效,所以就用指标了)
/** 检测日期的差值,小于7 */ IIf(DateDiff("d",CDate([SaikuUseDate].[SaikuUseDate].CurrentMember.Name), now())> 7, "yes", "no") /** 检测日期差值大于0并且小于7 (显示最近一周的数据) 但是其他年份的相同月份的数据也会显示出来*/ IIF(datediff("y",cdate(now()),cdate([SaikuUseDate].[SaikuUseDate].CurrentMember.Name))<=7, IIF(datediff("y",cdate(now()),cdate([SaikuUseDate].[SaikuUseDate].CurrentMember.Name))>=0,"週數據","非週數據"),"非週數據") //处理不同年份的日期差值问题(固定年份差值为0,表示只判定当年的数据) year(now()) 取的值为2019 IIF(datediff("y",cdate(now()),cdate([SaikuUseDate].[SaikuUseDate].CurrentMember.Name))<=7, IIF(datediff("y",cdate(now()),cdate([SaikuUseDate].[SaikuUseDate].CurrentMember.Name))>=0, IIF( year(cdate(now())) - year(cdate([SaikuUseDate].[SaikuUseDate].CurrentMember.Name))=0,"週數據","非週數據"),"非週數據"),"非週數據")
其中SaikuUseDate是我自定义的日期维度信息,在schame中的定义如下:
<Dimension name="SaikuUseDate" foreignKey="ID" > <Hierarchy hasAll="true" primaryKey="ID" allMemberName="SaikuUseDate"> <Level name="SaikuUseDate" column="saikuUseDate" type='Date' uniqueMembers="false" /> </Hierarchy> </Dimension>
区分最近一周数据与其他数据最终的MDX表达式语句为:
IIF(datediff("y",cdate(now()),cdate([SaikuUseDate].[SaikuUseDate].CurrentMember.Name))<=7, IIF(datediff("y",cdate(now()),cdate([SaikuUseDate].[SaikuUseDate].CurrentMember.Name))>=0, IIF( year(cdate(now())) - year(cdate([SaikuUseDate].[SaikuUseDate].CurrentMember.Name))=0,"週數據","非週數據"),
"非週數據"),
"非週數據")
saiku中添加新的指标信息如下:
根据新指标信息查询结果如下:
数据已筛选好了,接下来只需要把 新指标 週數據 字段按照 週數據 與 非週數據 进行筛选就可以啦。
(目前因为saiku是社区版的,过滤不起作用所以没法演示了,后期如果解决了过滤问题会更新的)
实现默认查询一周数据方案一:更改源代码
saiku在本地进行的编译的方式前面已有教程说明,接下来就是更改原代码了 (从网上学得教程,目前只了解到获取最新一天的数据信息)
参考博客地址: https://blog.csdn.net/zstao168/article/details/52818569
1. 主要更改的类信息:在saiku-web工程中的Query2Resource.java中,具体类路径为: /saiku-web/src/main/java/org/saiku/web/rest/resources/Query2Resource.java
在该类的 public QueryResult execute(ThinQuery tq ) 方法中添加 tq = this.restrictQueryByDate(tq); (execute方法大概在该类的 185-220行左右)
/**
*
* Execute a Saiku Query
* @summary Execute Query
* @param tq Thin Query model
* @return A query result set.
*/
@POST
@Consumes({"application/json" })
@Path("/execute")
public QueryResult execute(ThinQuery tq) {
//add code to limit query date
tq = this.restrictQueryByDate(tq);
try {
if (thinQueryService.isMdxDrillthrough(tq)) {
Long start = (new Date()).getTime();
ResultSet rs = thinQueryService.drillthrough(tq);
QueryResult rsc = RestUtil.convert(rs);
rsc.setQuery(tq);
Long runtime = (new Date()).getTime()- start;
rsc.setRuntime(runtime.intValue());
return rsc;
}
QueryResult qr = RestUtil.convert(thinQueryService.execute(tq));
ThinQuery tqAfter = thinQueryService.getContext(tq.getName()).getOlapQuery();
qr.setQuery(tqAfter);
return qr;
}
catch (Exception e) {
log.error("Cannot execute query (" + tq + ")",e);
String error = ExceptionUtils.getRootCauseMessage(e);
return new QueryResult(error);
}
}
在Query2Resource.java类中添加 ThinQuery restrictQueryByDate(ThinQuery tq) 方法,内容如下
// add code for query limit private ThinQuery restrictQueryByDate(ThinQuery tq) { ThinQueryModel queryModel = tq.getQueryModel(); Map<AxisLocation, ThinAxis> axesMap = queryModel.getAxes(); NamedList<ThinHierarchy> namedList = new NamedListImpl<ThinHierarchy>(); ThinAxis filterAxis = axesMap.get(AxisLocation.FILTER); List<ThinHierarchy> filterHie = filterAxis.getHierarchies(); namedList = this.resetThinHierachy(filterHie); //将修改后的Row重新set到queryModel if(namedList.size() > 0) { ThinAxis newFilterAxis = new ThinAxis( AxisLocation.FILTER, namedList, filterAxis.isNonEmpty(), filterAxis.getAggregators() ); axesMap.put(AxisLocation.FILTER,newFilterAxis); } //将修改后的Row重新set到queryModel if(namedList.size() == 0) { ThinAxis rowAxis = axesMap.get(AxisLocation.ROWS); List<ThinHierarchy> rowHie = rowAxis.getHierarchies(); namedList = this.resetThinHierachy(rowHie); if(namedList.size() > 0) { ThinAxis newRowsAxis = new ThinAxis( AxisLocation.ROWS, namedList, rowAxis.isNonEmpty(), rowAxis.getAggregators() ); axesMap.put(AxisLocation.ROWS,newRowsAxis); } } //if columns contained date member //if contained and have not set the limit ,then add limit to one day ,if do not hava then add this column and limit to one day; if(namedList.size() == 0) { // namedList.clear(); ThinAxis colAxis = axesMap.get(AxisLocation.COLUMNS); List<ThinHierarchy> colHie = colAxis.getHierarchies(); namedList = this.resetThinHierachy(colHie); if(namedList.size() == 0) { //if list is empty,then column don't hava date ,then add colHie to list and enfore to add date member; namedList.addAll(colHie); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); String yesterday = format.format(new Date(new Date().getTime() - 24 * 60 * 60 * 1000)); String newDateMdx = "[SaikuUseDate].[SaikuUseDate].["+yesterday+"]"; ThinMember thinMember = new ThinMember(yesterday,newDateMdx,yesterday); ThinHierarchy thinHie = new ThinHierarchy(); thinHie.setName("[SaikuUseDate].[SaikuUseDate]"); List<ThinMember> thinMemberList = new ArrayList<ThinMember>(); thinMemberList.add(thinMember); ThinSelection selection = new ThinSelection(); selection.setMembers(thinMemberList); selection.setType(ThinSelection.Type.INCLUSION); ThinLevel thinLevel = new ThinLevel(yesterday,yesterday,selection,null); // thinLevel.setSelection(selection); Map<String,ThinLevel> mapLevel = new LinkedHashMap<String,ThinLevel>(); mapLevel.put("SaikuUseDate", thinLevel); thinHie.setLevels(mapLevel); namedList.add(thinHie); ThinAxis newColAxis = new ThinAxis( AxisLocation.COLUMNS, namedList, colAxis.isNonEmpty(), colAxis.getAggregators() ); axesMap.put(AxisLocation.COLUMNS,newColAxis); } } return tq; } private NamedList<ThinHierarchy> resetThinHierachy(List<ThinHierarchy> hieList) { NamedList<ThinHierarchy> namedList = new NamedListImpl<ThinHierarchy>(); boolean flag = false; for(ThinHierarchy hie : hieList) { if(hie.getName().equals("[SaikuUseDate].[SaikuUseDate]")) { if(hie.getLevels().get("SaikuUseDate").getSelection() == null) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); String yesterday = format.format(new Date(new Date().getTime() - 24 * 60 * 60 * 1000)); String newDateMdx = "[SaikuUseDate].[SaikuUseDate].["+yesterday+"]"; ThinMember thinMember = new ThinMember(null,newDateMdx,yesterday); List<ThinMember> thinMemberList = new ArrayList<ThinMember>(); thinMemberList.add(thinMember); ThinSelection selection = new ThinSelection(); selection.setMembers(thinMemberList); hie.getLevels().get("SaikuUseDate").setSelection(selection); } flag = true; } namedList.add(hie); } if(flag) return namedList; namedList.clear(); return namedList; }
ps: 如果 hie.getLevels().get("SaikuUseDate") 中得到的ThinLevel对象没有setSeletion(selection)方法,需要手工在ThinLevel中添加set方法
还有一点需要注意,就是加上这些代码之后,saiku的schame文件中cube需要有 SaikuUseDate 日期字段。
最后将整个项目打包编译即可,将新的saiku-server启动,然后配置一些数据信息,便能获取最近一天的数据信息了。