【JIT/极态云】技术文档--聚合表

137 阅读11分钟

一、简介

聚合表是一种可以对多个数据表进行聚合计算和预处理的数据模型。在业务分析场景中,聚合表主要用于提高查询性能和简化复杂计算。 聚合表通过对原始明细表进行计算和整合,生成按特定维度分组的数据集。同时跨越多个数据表,将不同来源的数据聚合在一起。

image.png 聚合表中的数据可以由组件通过关联查询和关联数据去调用展示,但聚合表本身不可编辑。

二、交互流程

在创建新聚合表后,进入聚合表编辑器。从编辑器左侧的数据表列表中可以拖拽需要作为数据源的表至右侧聚合区域。在聚合区域点击每个数据表的节点可以查看对应表数据。

image.png 不同的数据表之间支持三种聚合方式,分别是:横向连接、追加合并、分组汇总。

image.png 选择聚合方式后,根据对应聚合方式的引导,完成节点配置及数据配置,聚合成最终所需的新表。

image.png 点击聚合节点的数据配置即可预览聚合后的数据效果,支持基于聚合结果增加公式字段、过滤行列。

image.png

三、聚合方式

聚合表提供了三种聚合方式,分别是横向连接、追加合并、分组汇总,适应了不同的聚合场景。

(一)横向连接

横向连接以数据表行记录为基础,进行多表之间数据的拼接,兼容各表字段。

image.png

1.设置连接方式

连接方式包括了内连接、左连接、右连接、全连接四种,连接方式不影响最终聚合表的表头,即表头均为连接各表字段之和。假设我们有两张数据表,分别记录学生与成绩信息。

image.png 运用不同连接方式的聚合结果如下:

内连接

在内连接方式中,取两表数据交集。

image.png 只取拼接两表之间有匹配字段值的记录行,若无法匹配不计入最终记录行,以下为实际聚合示例:

image.png 左连接

在左连接方式中,取两表数据交集以及主表自有部分。

image.png 以拼接主表为主,依次匹配相应的记录行并合并,若无法匹配则相应从表字段置为空值,以下为实际聚合示例:

image.png 右连接

在右连接方式中,取两表数据交集以及从表自有部分。

image.png 以拼接从表为主,依次匹配相应的记录行并合并,若无法匹配则相应主表字段置为空值,以下为实际聚合示例:

image.png 全连接

在全连接方式中,取两表数据并集。

image.png 无论两表之间是否有匹配的记录行,分别以主/从表为主进行合并,若无法匹配则相应主从表字段置为空值,以下为实际聚合示例:

image.png

2.设置连接字段

选择连接两张数据表中匹配的字段,字段类型需兼容。连接字段不要求有唯一匹配限制,可一对多匹配。

(二)追加合并

追加合并是直接将两张数据表字段合并,字段名称及类型相同的则自动去重。而对于最终聚合表行记录中新增的字段取值均置为空。

追加合并不进行字段匹配(数据层面的连接),因此最终聚合表行数等于主从表记录行数之和。

image.png 在节点配置中可以预览显示追加合并字段结果,对于没有匹配去重的字段,可添加同类型字段替代填充。或者对于已自动匹配的字段也可以删除置空。

(三)分组汇总

通过选择分组字段将表内数据进行归并,且根据汇总字段的统计方式进行聚合计算。

image.png

1.分组字段

分组字段作为数据分类的关键字,可添加多个分组字段。在汇总时按照分组字段次序依次划分。

其中地址/日期类型支持细分维度分组。

  • 地址字段支持的维度方式有:省、市、区;
  • 日期时间字段支持的维度方式有:年、年-季度、年-月、年-周、年-月-日、季度、月、周、日;

2.统计字段

根据选择的字段按照已有分组进行统计计算,可添加筛选条件对需要剔除统计的数据进行过滤。

不同的数据类型支持统计方式有所差异。

  • 数据/金额/百分比类型字段的统计方式支持:求和、已填写数、未填写数、去重计数、最大值、最小值、平均值;
  • 富文本、图片、附件、地址、定位、超链接类型字段的统计方式支持:已填写数、未填写数;
  • 检查框类型字段的统计方式支持:已选中数、未选中数;
  • 编号类型字段仅支持去重计数;
  • 流水号类型字段不支持统计;
  • 其余字段的统计方式支持:已填写数、未填写数、去重计数。

四、数据配置

在完成节点配置后,可以在数据配置中预览数据聚合结果,并支持基于结果的筛选/调整行列,或者新增额外的公式字段。

image.png

(一)添加公式字段

若需要统计基于现有聚合结果字段的逻辑值,可以添加公式字段,利用计算公式模块。该字段能结合已有字段进行一系列逻辑计算后输出相应统计结果。

image.png 当前已支持基本数值运算规则及数值、日期、文本常用取值方法,同时也允许通过复杂程序语法来进行部分逻辑运算。

(二)字段显隐

针对聚合结果,可以通过设置字段显示/隐藏,来筛选需要保留展示的字段列。

image.png 默认展示所有聚合拼接后的字段列表,可以通过勾选调整隐藏。对于添加的公式字段不支持显隐。

(三)数据筛选

针对聚合结果,也可以通过设置筛选条件筛选条件,来过滤保留所需要的数据记录行。

image.png 筛选支持单一条件和组条件的形式,搭配多种不等式/等式/范围等判断,检索相应符合条件的数据。

五、模型函数

聚合表类似于数据库中视图的定位,因此只支持对于表数据的查询,而不能增删改。

(一)类函数

image.png

(二)成员函数

image.png 因为聚合表模型是继承模型基类的,所以也可以直接使用模型基类中的成员函数。

image.png

六、函数设计

在模型构建模块中,我们统一提供了函数设计组件,以供对模型本身进行操作方法层面的扩展。

参见在模型简介中有相应函数设计模块说明。

七、代码实现

在聚合表的代码区中包含了两个文件,分别是e.json和model.py。

e.json是对聚合表元素的声明,包含了类型、存储路径、名称等信息。

{
    "type": "models.AggrType",
    "path": "models",
    "title": "成交统计",
    "backendBundleEntry": ".",
    "fromDb": 0
}

而model.py则是聚合表的具体构造实现,以及相关函数逻辑。


from models.AggrType import AggrModel
from datatypes.Meta import datatypes

class sold(AggrModel):
    f_RfvxeP = datatypes.Serial(name = "f_RfvxeP" , title = "流水号" , readOnly = 1 , description = "" , placeholder = "" , prefix = "DD" , connector = "" , dateTimeFormat = "YYYYMMDD" , incNum = 2 , startNumber = 1 , fieldId = "")
    f_FSjPsD = datatypes.AutoInt(name = "f_FSjPsD" , title = "客户" , readOnly = 1 , description = "" , placeholder = "" , relateFieldTitle = "")
    f_yCneuS = datatypes.Member(name = "f_yCneuS" , title = "业务人员" , readOnly = 1 , description = "" , placeholder = "" , selectionWay = "custom" , availableUser = {} , allowLeave = 0 , mulLevelSelectionConfig = [])
    f_yibFzQ = datatypes.Dept(name = "f_yibFzQ" , title = "业务部门" , readOnly = 1 , description = "" , placeholder = "" , selectionWay = "custom" , availableDeptId = None , mulLevelSelectionConfig = None , availableParentDeptId = None)
    f_MfoGRk = datatypes.Money(name = "f_MfoGRk" , title = "订单总价" , readOnly = 1 , description = "" , placeholder = "" , maxDigits = 18 , decimal = 2 , unit = "元")
    f_AUwaJZ = datatypes.Ltext(name = "f_AUwaJZ" , title = "备注" , readOnly = 1 , description = "" , placeholder = "" , limit = False , maxLen = 1024 , minLen = 0)
    f_cqanMi = datatypes.File(name = "f_cqanMi" , title = "合同附件" , readOnly = 1 , description = "" , placeholder = "" , maxCount = 5 , maxSize = 20 , selectedDown = False , selectedDelete = False , selectedDownUser = None , selectedDeleteUser = None)
    f_mFjkNd = datatypes.Date(name = "f_mFjkNd" , title = "签订日期" , readOnly = 1 , description = "" , placeholder = "" , dateTimeType = "DAY" , dateTimeFormat = "YYYY-MM-DD" , createDefault = False , updateDefault = False , autoAssign = None)
    f_psoTgX = datatypes.Datetime(name = "f_psoTgX" , title = "到期时间" , readOnly = 1 , description = "" , placeholder = "" , dateTimeType = "SECOND" , dateTimeFormat = "YYYY-MM-DD HH:mm:ss" , createDefault = False , updateDefault = False , autoAssign = None)
    f_EQWzec = datatypes.AutoInt(name = "f_EQWzec" , title = "主键ID" , readOnly = 1 , description = "" , placeholder = "" , maxDigits = 18 , decimal = 0 , unit = None)
    f_AvbhdP = datatypes.Stext(name = "f_AvbhdP" , title = "客户名称" , readOnly = 1 , description = "" , placeholder = "" , limit = False , maxLen = 255 , minLen = 0)
    f_PnqDle = datatypes.Radio(name = "f_PnqDle" , title = "客户状态" , readOnly = 1 , description = "" , placeholder = "" , color = True , options = [{"label": "线索", "value": "线索", "style": {"backgroundColor": "#CDE7FF", "color": "#CDE7FF"}}, {"value": "商机", "label": "商机", "style": {"backgroundColor": "#FFDDDA", "color": "#FFDDDA"}}, {"value": "成交", "label": "成交", "style": {"backgroundColor": "#FEEECA", "color": "#FEEECA"}}, {"value": "续签", "label": "续签", "style": {"backgroundColor": "#bddfdb", "color": "#bddfdb"}}] , selectionWay = "custom" , allowManualInput = False , mulLevelSelectionConfig = {"sortFieldName": "", "sortBy": "", "matchFieldName": "", "dataSourceModel": "", "filterValue": ""})
    f_zxKYaF = datatypes.Radio(name = "f_zxKYaF" , title = "客户来源" , readOnly = 1 , description = "" , placeholder = "" , color = False , options = [{"label": "渠道", "value": "渠道", "style": {"backgroundColor": "#FFDDDA", "color": "#FFDDDA"}}, {"label": "官网", "value": "官网", "style": {"backgroundColor": "#FEEECA", "color": "#FEEECA"}}, {"label": "推流", "value": "推流", "style": {"backgroundColor": "#E4F7E0", "color": "#E4F7E0"}}, {"label": "自拓客", "value": "自拓客", "style": {"backgroundColor": "#CFEFF4", "color": "#CFEFF4"}}] , selectionWay = "custom" , allowManualInput = False , mulLevelSelectionConfig = {"sortFieldName": "", "sortBy": "", "matchFieldName": "", "dataSourceModel": "", "filterValue": ""})
    f_EHcWfP = datatypes.Dropdown(name = "f_EHcWfP" , title = "行业分类" , readOnly = 1 , description = "" , placeholder = "" , color = False , options = [{"label": "A农、林、牧、渔业", "value": "A农、林、牧、渔业", "style": {"backgroundColor": "#FFDDDA", "color": "#FFDDDA"}}, {"label": "B采矿业", "value": "B采矿业", "style": {"backgroundColor": "#FEEECA", "color": "#FEEECA"}}, {"label": "C制造业", "value": "C制造业", "style": {"backgroundColor": "#E4F7E0", "color": "#E4F7E0"}}, {"label": "D电力、热力、燃气及水生产和供应业", "value": "D电力、热力、燃气及水生产和供应业", "style": {"backgroundColor": "#CFEFF4", "color": "#CFEFF4"}}, {"label": "E建筑业", "value": "E建筑业", "style": {"backgroundColor": "#D5F5EF", "color": "#D5F5EF"}}, {"label": "F批发和零售业", "value": "F批发和零售业", "style": {"backgroundColor": "#BED3E5", "color": "#BED3E5"}}] , allowManualInput = False , selectionWay = "custom" , mulLevelSelectionConfig = {"sortFieldName": "", "sortBy": "", "matchFieldName": "", "dataSourceModel": "", "filterValue": ""})
    f_ezrBkJ = datatypes.Address(name = "f_ezrBkJ" , title = "客户地址" , readOnly = 1 , description = "" , placeholder = "" , addressFormat = "pca" , detail = True)
    f_OxygvD = datatypes.Stext(name = "f_OxygvD" , title = "主要联系人" , readOnly = 1 , description = "" , placeholder = "" , limit = False , maxLen = 255 , minLen = 0)
    f_yresXj = datatypes.Phone(name = "f_yresXj" , title = "手机号" , readOnly = 1 , description = "" , placeholder = "" , rules = 0)
    f_HcyPMf = datatypes.Member(name = "f_HcyPMf" , title = "业务人员" , readOnly = 1 , description = "" , placeholder = "" , selectionWay = "custom" , availableUser = {} , allowLeave = 0 , mulLevelSelectionConfig = [])
    f_lbqUwe = datatypes.Radio(name = "f_lbqUwe" , title = "归属情况" , readOnly = 1 , description = "" , placeholder = "" , color = True , options = [{"label": "公海客户", "value": "公海客户", "style": {"backgroundColor": "#CDE7FF", "color": "#CDE7FF"}}, {"label": "私有客户", "value": "私有客户", "style": {"backgroundColor": "#FFDEEB", "color": "#FFDEEB"}}] , selectionWay = "custom" , allowManualInput = False , mulLevelSelectionConfig = {"sortFieldName": "", "sortBy": "", "matchFieldName": "", "dataSourceModel": "", "filterValue": ""})
    f_oFQtsh = datatypes.Date(name = "f_oFQtsh" , title = "最新跟进日期" , readOnly = 1 , description = "" , placeholder = "" , dateTimeType = "DAY" , dateTimeFormat = "YYYY-MM-DD" , createDefault = False , updateDefault = False , autoAssign = None)
    f_KJhDZv = datatypes.Date(name = "f_KJhDZv" , title = "下次跟进日期" , readOnly = 1 , description = "" , placeholder = "" , dateTimeType = "DAY" , dateTimeFormat = "YYYY-MM-DD" , createDefault = False , updateDefault = False , autoAssign = None)
    class Meta:
        modelType = "AggrType"
        db = ""
        dataTitle = None
        dbTable = "Select([F("T_AjXaRD.drillNo1", "f_RfvxeP"), F("T_AjXaRD.customer", "f_FSjPsD"), F("T_AjXaRD.salesman", "f_yCneuS"), F("T_AjXaRD.operationalComponent", "f_yibFzQ"), F("T_AjXaRD.total_price", "f_MfoGRk"), F("T_AjXaRD.remarks", "f_AUwaJZ"), F("T_AjXaRD.contract_annexs", "f_cqanMi"), F("T_AjXaRD.date", "f_mFjkNd"), F("T_AjXaRD.f353", "f_psoTgX"), F("T_RCAIxV.id", "f_EQWzec"), F("T_RCAIxV.cName", "f_AvbhdP"), F("T_RCAIxV.status", "f_PnqDle"), F("T_RCAIxV.sources", "f_zxKYaF"), F("T_RCAIxV.industry", "f_EHcWfP"), F("T_RCAIxV.address", "f_ezrBkJ"), F("T_RCAIxV.contactor", "f_OxygvD"), F("T_RCAIxV.phone", "f_yresXj"), F("T_RCAIxV.sales", "f_HcyPMf"), F("T_RCAIxV.attribution", "f_lbqUwe"), F("T_RCAIxV.latest_followup_date", "f_oFQtsh"), F("T_RCAIxV.next_followup_date", "f_KJhDZv")], From([Select([F("drillNo1"), F("customer"), F("salesman"), F("operationalComponent"), F("total_price"), F("remarks"), F("contract_annexs"), F("date"), F("f353")], From(["models.OrderModel"])), "T_AjXaRD"], LeftJoin(Select([F("id"), F("cName"), F("status"), F("sources"), F("industry"), F("address"), F("contactor"), F("phone"), F("sales"), F("attribution"), F("latest_followup_date"), F("next_followup_date")], From(["models.CustomerModel"])),"T_RCAIxV"), On([F("T_AjXaRD.customer"), "=", F("T_RCAIxV.id")])), "横向连接")"
        name = "sold"
        baseModel = ""
        
  • 展示字段,对于当前最终聚合的表需要展示的字段声明,包括字段名称类型等。
  • 聚合表构造,主要是针对多层次聚合节点的拼接逻辑,转换为T表达式进行的存储,

八、使用效果

image.png 聚合表除了正常在函数设计中调用模型函数以外,也可以在页面组件中作为数据源配置。

九、使用场景示例

比如在销售部门需要对本部门所有销售人员进行销售额的统计,并以图表形式展示时,就需要依赖各个人员的销售统计数据。此时运用聚合表就可以很快的构建数据源。

image.png 如图所示,通过将“订单表”与“客户表”进行横向连接后,可以获得拼接后的第一级表。基于此表再次进行分组汇总,选择“业务人员”为分组字段,“订单总价”为统计字段并使用“求和”方式。即可得到最终的聚合表。

image.png 最终聚合统计结果就是展示每一个业务人员成单的订单总价,如此便可用于图表上的展示。

十、注意事项

  1. 聚合表中的关联数据和子表字段不再具有关联查询的特性,只是作为普通的关联主键存在。若需要展示对应关联模型的数据,需要进行聚合连接。
  2. 在构建聚合表时,每一层聚合结果的字段独立继承,即若在上一层聚合节点将部分字段隐藏后,这些字段不会出现在下一层聚合结果中。

进一步了解极态云,体验产品?

请访问 极态云官网