Skip to content

衡石 HQL ​

衡石系统中自定义的计算过程描述语言为 Hengshi SENSE Query Language (HQL) ,用于衡石系统的前后端交互、API 数据请求中。

语法规定 ​

使用统一的 JSON 来描述各个计算过程. HQL 由多层调用的 HE (Hengshi Expression) 组成。下面是单个 HE 的语法结构。

HE 节点名类型是否必须描述
uidSTRING否本节点的全局唯一标识符
kindSTRING是节点类型,见HE状态说明
opOBJECT是不同的 HE 类型,对应不同的节点定义,见HE状态说明
argsHE 数组否当 kind 为 functions的时候,此项为必须的
typeSTRING否本节点输出的数据类型,可以是 string, number, integer, date, time, json, bool 中的一种
datasetOBJECT否本节点所在的数据集 id, 一般在 kind 为 field 的时候会指定字段所属的数据集
directionSTRING否可选值为 asc 或者 desc,本节点用户排序的时候可以指定该字段,不指定的话,默认为 asc
windowOBJECT否指定本节点计算的窗口,只有 kind 为 function 时,该字段的值才有效,见HEWindow窗口说明
filterHE 数组否计算的过滤条件,一般用户聚合计算的过滤

HE 节点类型说明 ​

节点类型节点描述类型对应的 op
field描述字段字段名
function描述函数函数名
reference描述引用字段,一般用户图表的定义中引用的名字
constant描述常量常量的值
formula描述自定义的 HE 表达式表达式的定义
array描述数组数组
attr描述用户属性用户属性的名字
param描述应用参数应用参数的名字
dataset描述数据集数据集的 id

HE Window 窗口说明 ​

窗口关键字类型描述
partitionHE 数组计算过程的划分依据,对应 sql 中的 partition by 关键字
orderHE 数组计算过程的排序依据,对应 sql 中的 order by 关键字

示例1:描述字段 ​

kind 的值是 field, op 的值是字段名, dataset 的值是字段所在的数据集 id。下面的例子描述的是来自数据集 1 的 "test" 字段

json
{
   "kind": "field",
   "op": "test",
   "dataset": 1
}

示例2:描述常量 ​

kind 的值是 constant, op 的值是常量值, type 的值是常量的类型。type 为非必需的。 下面的例子描述的是字符串类型常量值 'test'

json
{
   "kind": "constant",
   "op": "'test'"
}

下面的例子描述的是时间类型的常量值 '2000-01-01'

json
{
   "kind": "constant",
   "op": "'2000-01-01'",
   "type": "date"
}

示例3:描述函数 ​

kind 的值是 function, op 的值是函数名或者操作符, args 是函数参数数组。 下面的例子是描述一个加法操作,数据集 2 的字段 salesNum + 2000。

json
{
   "kind": "function",
   "op": "+",
   "args": [
        {
             "kind": "field",
             "op": "salesNum",
             "dataset": 2
        },
        {
             "kind": "constant",
             "op": 2000
        }
   ]
}

下面的例子是描述聚合函数 sum 的使用,计算 数据集 2 的 salesNum 字段列的求和。

json
{
   "kind": "function",
   "op": "sum",
   "args": [
        {
             "kind": "field",
             "op": "salesNum",
             "dataset": 2
        }
   ]
}

下面的例子是描述窗口函数 avg 的使用,以 数据集 2 的 location 字段为分组,计算 数据集 2 的 salesNum 字段列的平均值。

json
{
   "kind": "function",
   "op": "avg",
   "args": [
        {
             "kind": "field",
             "op": "salesNum",
             "dataset": 2
        }
   ],
   "window": {
        "partition": [
             {
                 "kind": "field",
                 "op": "location",
                 "dataset": 2
             }
        ]
   }
}

下面的例子是描述窗口函数 rank 的使用,根据数据集 2 的 saleNum 字段求和的降序对数据集 2 的 location 字段排名。

json
{
   "kind": "function",
   "op": "avg",
   "args": [
        {
             "kind": "field",
             "op": "location",
             "dataset": 2
        }
   ],
   "window": {
        "order": [
             {
                 "kind": "function",
                 "op": "sum",
                 "args": [{
                     "kind": "field",
                     "op": "saleNum",
                     "dataset": 2
                  }],
                 "direction": "desc"
             }
        ]
   }
}

下面的例子是描述带 filter 条件的聚合函数 sum 的使用,计算所有 location 为"北京"或者"上海"的条件下, 数据集 2 的 salesNum 字段列的求和。

json
{
   "kind": "function",
   "op": "sum",
   "args": [
        {
             "kind": "field",
             "op": "salesNum",
             "dataset": 2
        }
   ],
   "filter": [
        {
             "kind": "function",
             "op": "in",
             "args":[
                {
                     "kind": "field",
                     "op": "location",
                     "dataset": 2
                },
                {
                     "kind": "constant",
                     "op": ["北京", "上海"]
                }
             ]
        }
   ]
}

示例4:描述表达式 ​

kind 的值是 formula, op 的值是表达式。函数表达式的使用请参照函数文档。 HE 函数的描述都可以转成HE 表达式,例子中也对应了上面函数描述的例子。下面是HE 以及对应 表达式表述的定义。

用途HE表达式
字段{“kind”: “field”, “op”:”字段名”}{字段名}
数据集的字段{“kind”: “field”, “op”:”字段名”, "dataset":"数据集id"}{{数据集}}.{字段名}
用户属性{“kind”: “attr”, “op”:”用户属性名”}{{$用户属性}}
应用参数{“kind”: “param”, “op”:”应用参数名”}{{%应用参数}}
函数{“kind”: “function”, “op”:”函数名”, "args":["arg1", "arg2"]}函数名(arg1, arg2)
窗口函数{“kind”: “function”, “op”:”函数名”, "args":["arg1", "arg2"],"window":{"partition":["分组"],"order":["排序"]}}函数名(arg1, arg2) over(partition by "分组" order by "排序")
带过滤函数{“kind”: “function”, “op”:”函数名”, "args":["arg1", "arg2"],"filter":["filter1","filter2"]}函数名(arg1, arg2) filter(where "filter1" and "filter2")

下面的例子描述的是连接数据集 1 的 firstname 列 和 数据集 1 的 lastname 列。

json
{
   "kind": "formula",
   "op": "concat({{1}}.{firtname}, {{1}}.{lastname})"
}

下面的例子描述的是比较 数据集 1 的 salesNum 字段 和 应用参数的基准值。

json
{
   "kind": "formula",
   "op": "{{1}}.{salesNum} > {{%基准值}}"
}

下面的例子是描述窗口函数 avg 的使用,以 数据集 2 的 location 字段为分组,计算 数据集 2 的 salesNum 字段列的平均值。

json
{
   "kind": "formula",
   "op": "avg({{2}}.{salesNum}) over(partition by {{2}}.{location})"
}

下面的例子是描述窗口函数 rank 的使用,根据数据集 2 的 saleNum 字段求和的降序对数据集 2 的 location 字段排名。

json
{
   "kind": "formula",
   "op": "rank({{2}}.{location}) over(order by sum({{2}}.{salesNum}) desc)"
}

下面的例子是描述带 filter 条件的聚合函数 sum 的使用,计算所有 location 为"北京"或者"上海"的条件下, 数据集 2 的 salesNum 字段列的求和。

json
{
   "kind": "formula",
   "op": "sum({{2}}.{salesNum}) filter(where in({{2}}.{location}, ['北京','上海']))"
}

使用场景1: 图表的定义 ​

在衡石系统中,定义一个图表由两部分组成,一部分是 HE 的定义,用于获取数据;另一部分是格式的定义,用于展示。这里我们只关注用于获取数据的 HE 部分。 下面是一个简单的图表示例,HE 的计算组合在一起,描述了业务:以 region_name 分组,计算组内 region_id 的求和,结果按照 region_name 的升序展示。

json
{
    "options": {
        "axes": [
            {
                "args": [
                    {
                        "op": "region_name",
                        "kind": "field",
                        "dataset": 7
                    }
                ],
                "op": "group",
                "uid": "u_edbee8adba68e26a_2",
                "kind": "function"
            },
            {
                "op": "sum",
                "kind": "function",
                "args": [
                    {
                        "op": "region_id",
                        "kind": "field",
                        "dataset": 7
                    }
                ],
                "uid": "u_9f886f9cb7bdf1d2_2"
            }
        ],
        "sort": [
            {
                "op": "u_edbee8adba68e26a_2",
                "kind": "reference",
                "direction": "asc"
            }
        ],
        "limit": 1000
    }
}

使用场景2: url 过滤 ​

访问衡石系统的共享链接时,可以在共享链接后面添加 url 过滤条件,用于数据的权限控制。这个过滤条件也是由 HE 组成的。 下面这个过滤表示过滤 location 为北京的数据,它会作用于所有的图表上。

text
where=[{"kind":"formula","op":"{location}='北京"}]

下面这个过滤表示过滤数据集 1 的 location 字段为北京的数据,它会作用于所有与数据集1 由关联的图表上。

text
where=[{"kind":"formula","op":"{1}.{location}='北京"}]

使用场景3: 数据集的新增字段和指标 ​

在衡石系统的数据集里新建字段、新建指标都是通过写 HE 表达式实现的。

HENGSHI SENSE API 使用手册