目前在公司的数据统计工作中存在以下问题:
1.指标数多,上千个指标要统一管理。
2.口径混乱,比如同样叫下单数,有的下单数包含全部订单,有的却只包含有效订单。
3.维度多,比如APP推广人员关系自己负责APP推广渠道产生的DAU,而各地的BD关心负责的省份或者城市的DAU,各个指标之间维度不同但是指标要一致。
4.如果分散管理,在修改某一类指标中的某一个时,很容易忘记修改本类中的其他指标,造成数据不一致。
为了解决这些矛盾,我们需要将以sql引擎为核心,将指标体系整合起来。
中心逻辑:将各个指标配置在数据库中,每一行作为一个指标,指标之间有继承关系,每个指标有自己特有的配置信息。当我们从已有的指标扩展参数时,在继承上一级指标口径的同时,整合自己本身的口径,就生成了一个新的sql。通过层层的继承,众多的指标生成了一个树形结构。局部示意如下。
在上图中从APP总体dau中加上操作系统的限制条件,就派生出了ios和android的dau,再在这两个指标上加上是否是新激活的口径就派生出了新激活或者非新激活,android和ios的dau这四个指标。
上面实现方式的好处是,当父节点中select部分,inner join,where部分发生变化,其下的所有后代节点都会同步发生变化。不会发生口径不一致的现象。当鼠标悬浮在节点上,会显示拼接好的sql。
具体的实现逻辑较为复杂,这里是说一下总体的思路:
假设我们我们目前有一个根节点为下单用户,根节点的sql如下:
SELECT
COUNT(DISTINCT mt.uid) as result
FROM db_main.tb_order AS mt
#INNER_JOIN
#WHERE
#GROUP_BY
其中带#号的是需要替换的占位符,假设这个根节点有一个子节点为昨天的下单用户数,那么这个子节点需要自带一个口径为
create_date='2018-04-10',替换到根节点生成新的sql如下:
SELECT
COUNT(DISTINCT mt.uid) as result
FROM db_main.tb_order AS mt
#INNER_JOIN
create_date='2018-04-10'
#GROUP_BY
再假设,昨天的下单用户数有一个子节点为昨日有效下单用户数,那么这个子节点需要自带一个口径:order_status=1,替换之后生成:
SELECT
COUNT(DISTINCT mt.uid) as result
FROM db_main.tb_order AS mt
#INNER_JOIN
create_date='2018-04-10' AND order_status=1
#GROUP_BY
如此繁复。
以上只是个总体的思路,在实践过程中还遇到了很多别的问题,比如,不是所有的限制条件都可以用where和inner join来解决,会有很多跨数据库的实例的查询,很多限制条件是动态的,很多现实条件需要预先加工,这就需要我们运用多层级,无限递归的占位符来解决,并预先设置占位符和限制条件的类,生成sql的时候利用配置实例化占位符和限制条件,灵活的生成sql。