首页 > 其他分享 >Kingbase ES 自定义聚合函数和一次改写案例

Kingbase ES 自定义聚合函数和一次改写案例

时间:2023-09-18 16:23:41浏览次数:35  
标签:聚合 函数 自定义 -- into Kingbase values ES

文章概要:

KES的SQL的语法暂时不兼容oracle的自定义聚合函数的创建语法和流程,但是可以使用KES已支持的语法改写。
本文整理和简单解析了自定义聚合函数的原理和解读了范例代码。
并根据客户代码进行了改写。

一,oracle自定义聚合函数的简析

oracle的自定义聚合函数需要实现4个ODCIAggregate 接口函数,被声明和定义在一个对象类型中。
这些函数定义了任何一个聚集函数内部需要实现的操作,
这些函数分别是 initialization, iteration, merging(定义了并行聚合enable parallel时会调用) 和 termination。如下图是自定义聚合函数的处理流程:

1,自定义聚合函数的并行流程:

               |--------------|
               |              |
              \|/             |
ODCIAggregateInitialize ------->  ODCIAggregateIterate
                        |
                        |
                        | -----> ODCIAGGREGATEMERGE -----> ODCIAGGREGATETERMINATE
                        |
               |--------------| 
               |              |
              \|/             | 
ODCIAggregateInitialize ------->  ODCIAggregateIterate

自定义聚合函数的串行流程(实测不会调用ODCIAGGREGATEMERGE):

               |--------------|
               |              |
              \|/             |
ODCIAggregateInitialize------->   ODCIAggregateIterate -----> ODCIAGGREGATETERMINATE

从上可以看出,并行是会调用ODCIAGGREGATEMERGE,但是非并行未调用ODCIAGGREGATEMERGE。

2,oracle自定义聚合函数的实例解析


举一个计算第二大值得案例为例

接口的定义:

create type SecondMaxImpl as object
(
     --自定义保存最大值
     max NUMBER, 
     --自定义保存第二大值
     secmax NUMBER, 
     --初始化函数,必须要实现的方法,用于在聚合运算的最开始部分,初始化上下文环境  
     static function ODCIAggregateInitialize(sctx IN OUT SecondMaxImpl) return number,
     --迭代运算函数,oracle依据该函数进行迭代运算,
     --第一个参数self,为聚合运算的上下文,  
     --第二个参数value,为当前需要处理的值,可以为number varchar2等类型,  
     --在迭代过程中,如果当前值为null,则忽略该次迭代  
     member function ODCIAggregateIterate(self IN OUT SecondMaxImpl, value IN number) return number,
     --(oracle会有选择执行该步骤)该函数用于合并两个上下文到一个上下文中,在并行和串行环境下均有可能发挥作用 
     member function ODCIAggregateMerge(self IN OUT SecondMaxImpl, ctx2 IN SecondMaxImpl) return number,
     --该函数在聚合运算的最后一步运行,用于对结果进行处理并返回处理结果,  
     --第一个参数self为上下文,
     --第二个参数returnValue为返回值,可以为number,varchar2等类型  
     --第三个参数flags为标识位 
     member function ODCIAggregateTerminate(self IN SecondMaxImpl, returnValue OUT number, flags IN number) return number
);
/

--聚合函数的定义和接口实现

create or replace type body SecondMaxImpl is 
static function ODCIAggregateInitialize(sctx IN OUT SecondMaxImpl) 
return number is 
begin
   sctx := SecondMaxImpl(0, 0); --初始化
   return ODCIConst.Success;
end;

member function ODCIAggregateIterate(
    self IN OUT SecondMaxImpl, 
    value IN number
) 
return number 
is
begin
 if value > self.max then
    self.secmax := self.max;
    self.max := value;
 elsif value > self.secmax then
    self.secmax := value;
 end if;
 return ODCIConst.Success;
end;

member function ODCIAggregateMerge(
    self IN OUT SecondMaxImpl,  --合并两个上下文(并行聚合有用。只能用于并行聚合?)
    ctx2 IN SecondMaxImpl
) 
return number 
is
begin
   if ctx2.max > self.max then
       if ctx2.secmax > self.secmax then 
           self.secmax := ctx2.secmax;
       else
           self.secmax := self.max;
       end if;
       self.max := ctx2.max;
   elsif ctx2.max > self.secmax then
       self.secmax := ctx2.max;
   end if;
   return ODCIConst.Success;
end;

member function ODCIAggregateTerminate(
    self IN SecondMaxImpl, 
    returnValue OUT number, 
    flags IN number
) 
return number is
begin
 returnValue := self.secmax; --获取第二大值
 --returnValue := self.max; --获取最大值
 return ODCIConst.Success;
end;
end;
/
---创建聚合函数
CREATE FUNCTION SecondMax (input NUMBER) RETURN NUMBER 
PARALLEL_ENABLE AGGREGATE USING SecondMaxImpl;

--构造测试数据,看看运行效果

create table tt02(
    id int , 
    name varchar(20), 
    sal number(6,2)
);

insert into tt02 values(12,'aaaa',1253.2);
insert into tt02 values(14,'aass',1965.3);
insert into tt02 values(13,'vvvv',2056.6);
insert into tt02 values(16,'aass',6562.1);
insert into tt02 values(15,'aass',4563.4);
insert into tt02 values(12,'aaaa',2532.2);
insert into tt02 values(14,'aass',1965.3);
insert into tt02 values(13,'vvvv',6556.6);
insert into tt02 values(16,'aass',8965.1);
insert into tt02 values(15,'aass',7854.4);

--测试验证(符合预期)

SQL> select id,SecondMax(sal) from tt02 group by id;

    ID SECONDMAX(SAL)
---------- --------------
    12     1253.2
    13     2056.6
    14     1965.3
    16     6562.1

SQL> select /*+ parallel */ id,SecondMax(sal) from tt02 group by id;

    ID SECONDMAX(SAL)
---------- --------------
    12     1253.2    
    13     2056.6    
    14     1965.3    
    16     6562.1

--重新生成数据

delete from tt02;

declare
    vv1 int;
    vv2 int;
    vv3 varchar2(20);
begin
    for i in 1..10 loop
        select abs(mod(dbms_random.random,10000)) into vv1 from dual;
        select abs(mod(dbms_random.random,5)) into vv2 from dual;
        select dbms_random.string('u',5) into vv3 from dual; 
        insert into tt02 values(vv2,vv3,vv1);
    end loop;
end;

SQL> select * from tt02;

    ID NAME                      SAL
---------- ---------------------------------------- ----------
     3 IJTIJ                     5978
     4 JUAWT                     2087
     0 FPBMN                     2218
     0 AMBNZ                      618
     2 VFXJD                      37
     4 PEXGM                     7983
     2 CDQJT                      877
     2 ENQFX                     3359
     2 ICJFI                     1220
     0 XCGJX                     1397

10 rows selected.

--二次验证(符合预期)

SQL> select id,SecondMax(sal) from tt02 group by id;

    ID SECONDMAX(SAL)
---------- --------------
     0      1397
     2      1220   
     3       0   
     4      2087

SQL> select /*+ parallel */ id,SecondMax(sal) from tt02 group by id;

    ID SECONDMAX(SAL)
---------- --------------
     0      1397   
     2      1220   
     3       0   
     4      2087

实际上就改写而言,到此已经知道该函数的作用

二,KES语法改写oracle自定义聚合函数

1,oracle的自定义聚合函数定义及其分析验证

oracle自定义聚合函数sumc2如下,先对其进行一个简单的分析和功能验证:

--对象类型头(接口声明)
CREATE OR REPLACE EDITIONABLE TYPE "TYPESUMVARCHAR2" as object (
  vsum VARCHAR2(4000),
  --自定义聚集函数初始化设置,从这儿开始一个聚集函数
  static function ODCIAggregateInitialize(sctx IN OUT TYPESUMVARCHAR2) return number,
  --自定义聚集函数,最主要的步骤,这个函数定义我们的聚集函数具体做什么操作,后面的例子,是取最大值,最小值,平均值,还是做连接操作.self 为当前聚集函数的指针,用来与前面的计算结果进行关联
  member function ODCIAggregateIterate(self IN OUT TYPESUMVARCHAR2,value IN varchar2) return number,
  --终止聚集函数的处理,返回聚集函数处理的结果
  member function ODCIAggregateTerminate(self IN TYPESUMVARCHAR2,returnValue OUT VARCHAR2, flags IN number) return number,
  --用来合并两个聚集函数的两个不同的指针对应的结果,用户合并不同结果结的数据,特别是处理并行(parallel)查询聚集函数的时候.
  member function ODCIAggregateMerge(self IN OUT TYPESUMVARCHAR2,ctx2 IN TYPESUMVARCHAR2) return number

);

对象类型体(接口定义)

CREATE OR REPLACE EDITIONABLE TYPE BODY "TYPESUMVARCHAR2" IS
    --自定义聚集函数初始化设置,从这儿开始一个聚集函数
    STATIC FUNCTION ODCIAGGREGATEINITIALIZE(
        SCTX IN OUT TYPESUMVARCHAR2
    )
    RETURN NUMBER IS
    BEGIN
        SCTX := TYPESUMVARCHAR2('');
        --初始化vsum
        RETURN ODCICONST.SUCCESS;
    END;
    --自定义聚集函数,最主要的步骤,这个函数定义我们的聚集函数具体做什么操作,后面的例子,
    --是取最大值,最小值,平均值,还是做连接操作.self 为当前聚集函数的指针,用来与前面的计算结果进行关联
    MEMBER FUNCTION ODCIAGGREGATEITERATE(
        SELF IN OUT TYPESUMVARCHAR2,
        VALUE IN VARCHAR2
    ) RETURN NUMBER IS
    BEGIN
        --SELF.vsum := substr(SELF.vsum || ',' || VALUE,0,2000);
        IF instr(
            SELF.vsum,
            value
        ) = 0
        OR SELF.vsum IS NULL THEN
        SELF.vsum := substr(
            SELF.vsum || ',' || VALUE,
            0,
            2000
        ) ;
        ELSE
        SELF.vsum := substr(
            SELF.vsum || '',
            0,
            2000
        ) ;
        END IF ;
        RETURN ODCICONST.SUCCESS;
    END;
    --终止聚集函数的处理,返回聚集函数处理的结果,(代码做了截取)
    MEMBER FUNCTION ODCIAGGREGATETERMINATE(
        SELF IN TYPESUMVARCHAR2,
    RETURNVALUE OUT VARCHAR2,
        FLAGS IN NUMBER
    ) RETURN NUMBER IS
    BEGIN
        RETURNVALUE := SUBSTR(
            SELF.vsum,
            2
        );

        RETURN ODCICONST.SUCCESS;
    END;
    --用来合并两个聚集函数的两个不同的指针对应的结果,用户合并不同结果结的数据,特别是处理并行(parallel)查询聚集函数的时候.
    --此处默认未做任何动作(未执行合并)
    MEMBER FUNCTION ODCIAGGREGATEMERGE(
        SELF IN OUT TYPESUMVARCHAR2,
        CTX2 IN TYPESUMVARCHAR2
    ) 
    RETURN NUMBER IS
    BEGIN
        RETURN ODCICONST.SUCCESS;
    END;

END;

--创建自定义聚合函数

CREATE OR REPLACE FUNCTION  sumc2(input varchar2) 
RETURN varchar2
PARALLEL_ENABLE AGGREGATE 
USING TYPESUMVARCHAR2;

根据上面的tt02表实测

SQL> select * from tt02;

    ID NAME                      SAL
---------- ---------------------------------------- ----------
     3 IJTIJ                     5978
     4 JUAWT                     2087
     0 FPBMN                     2218
     0 AMBNZ                      618
     2 VFXJD                      37
     4 PEXGM                     7983
     2 CDQJT                      877
     2 ENQFX                     3359
     2 ICJFI                     1220
     0 XCGJX                     1397

SQL> select id,sumc2(name) from tt02 group by id;

ID SUMC2(NAME)
--------------------------------------------------------------------------------
0 FPBMN,XCGJX,AMBNZ
2 VFXJD,ICJFI,ENQFX,CDQJT
3 IJTIJ
4 JUAWT,PEXGM

更换表实测:

--teachers表如下:
 teacher_id | teacher_name | age |  sal  | gender | title  | position | department
------------+--------------+-----+----------+--------+----------+------------+------------
  10001001 | 陈思宇    | 46 | 15689.00 | 男   | 特级教师 | 校长    | 校长室
  10001002 | 文强     | 44 | 29942.00 | 男   | 特级教师 | 副校长   | 校长室
  10001003 | 吴玲     | 41 | 29142.00 | 女   | 高级教师 | 办公室主任 | 办公室
  10001004 | 章丽     | 41 | 28242.00 | 女   | 高级教师 | 教务处主任 | 教务处
  10001005 | 张志东    | 41 | 28242.00 | 男   | 高级教师 | 财务处主任 | 财务处
  10001006 | 熊浩宇    | 49 | 28356.00 | 女   | 一级教师 | 招生办主任 | 招生办
  10001007 | 朱雯     | 49 | 24016.00 | 女   | 一级教师 | 招生办助理 | 招生办
  10001008 | 张志强    | 49 | 23964.00 | 女   | 一级教师 | 财务处助理 | 财务处
  10001009 | 朱国斌    | 49 | 21974.00 | 男   | 二级教师 | 财务处助理 | 财务处

oracle测试结果

select age,sumc2(title) from teachers group by age;
41 高级教师
44 特级教师
46 特级教师
49 一级教师,二级教师

通过代码和实际效果的实测,聚合函数sumc2作用是去重,获取去重后的拼接结果。
了解了客户原生代码和oracle自定义聚合功能后,

2,KES所支持的聚合函数基本原理

KES能支持的聚合函数(PLPGSQL)语法如下:

CREATE AGGREGATE name ( [ argmode ] [ argname ] arg_data_type [ , ... ] ) (  
  SFUNC = sfunc,    ---迭代函数,每行数据迭代调用计算结果
  STYPE = state_data_type    ----聚合函数返回的数据类型
  [ , SSPACE = state_data_size ]  
  [ , FINALFUNC = ffunc ]   ----每组的最终计算函数,可选
  [ , FINALFUNC_EXTRA ]  
  [ , COMBINEFUNC = combinefunc ]   ---聚合COMBINEFUNC函数,开启后在开启PARALLEL能并行
  [ , SERIALFUNC = serialfunc ]  
  [ , DESERIALFUNC = deserialfunc ]  
  [ , INITCOND = initial_condition ]  ---INITCOND是第一次调用SFUNC给第一个参数的传值,可以不写。
  [ , MSFUNC = msfunc ]  
  [ , MINVFUNC = minvfunc ]  
  [ , MSTYPE = mstate_data_type ]  
  [ , MSSPACE = mstate_data_size ]  
  [ , MFINALFUNC = mffunc ]  
  [ , MFINALFUNC_EXTRA ]  
  [ , MINITCOND = minitial_condition ]  
  [ , SORTOP = sort_operator ]  
  [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]   ----SAFE并行聚合
)  

其中重点需要讲的是:

聚合函数是每组独立计算的,比如按上述teachers表的age聚合(GROUP BY age),那么就会分4组,4组分别内部进行计算。

--teachers表如下:
 teacher_id | teacher_name | age |  sal  | gender | title  | position | department
------------+--------------+-----+----------+--------+----------+------------+------------
  10001001 | 陈思宇    | 46 | 15689.00 | 男   | 特级教师 | 校长    | 校长室
  10001002 | 文强     | 44 | 29942.00 | 男   | 特级教师 | 副校长   | 校长室
  10001003 | 吴玲     | 41 | 29142.00 | 女   | 高级教师 | 办公室主任 | 办公室
  10001004 | 章丽     | 41 | 28242.00 | 女   | 高级教师 | 教务处主任 | 教务处
  10001005 | 张志东    | 41 | 28242.00 | 男   | 高级教师 | 财务处主任 | 财务处
  10001006 | 熊浩宇    | 49 | 28356.00 | 女   | 一级教师 | 招生办主任 | 招生办
  10001007 | 朱雯     | 49 | 24016.00 | 女   | 一级教师 | 招生办助理 | 招生办
  10001008 | 张志强    | 49 | 23964.00 | 女   | 一级教师 | 财务处助理 | 财务处
  10001009 | 朱国斌    | 49 | 21974.00 | 男   | 二级教师 | 财务处助理 | 财务处

1),SFUNC迭代函数,假设自定义如下:

CREATE OR REPLACE FUNCTION YOUR_SFUNC_NAME (numeric, numeric, numeric......)
RETURNS numeric
as
begin
    .......(省略)
end

这个函数就是每行数据的迭代函数

参数一:$1, 上一次迭代的计算结果;
参数二:$2, YOUR_AGGREGATE_NAME的第一个参数(如果聚合函数传入的是表的列,则表示当前行数据)
参数三:$3, YOUR_AGGREGATE_NAME的第二个参数(如果是个固定值,比如数值2,则每次传入2)
参数四:$4, YOUR_AGGREGATE_NAME的第三个参数

...........

2),FINALFUNC最终函数,假设自定义如下:

CREATE OR REPLACE FUNCTION YOUR_FINALFUNC_NAME (numeric)    ---只有一个参数,SFUNC函数返回的是numeric,所以这里是numeric
RETURNS numeric      ---聚合返回类型,所以这里是numeric
as
begin
    .......(省略)
end

通过YOUR_SFUNC_NAME函数将每组计算完后,,最后调用一次,也就是说最后还可以进行一次规则计算。

3),YOUR_AGGREGATE_NAME聚合函数
聚合函数的定义会引用到上述YOUR_SFUNC_NAME和YOUR_FINALFUNC_NAME函数,最终达成特定目标的计算。

一个典型的非并行使用举例;

CREATE AGGREGATE YOUR_AGGREGATE_NAME(numeric, numeric)    ---接受两个参数,会作为SFUNC函数的后两个参数
(
        INITCOND = xxxx,    ---INITCOND是第一次调用YOUR_SFUNC_NAME函数,给第一个参数的传值xxxx,可以不写。
        STYPE = numeric,     ---聚合函数返回的数据类型numeric
        SFUNC = YOUR_SFUNC_NAME,    ---每组的自定义迭代函数
        FINALFUNC = YOUR_FINALFUNC_NAME   ---每组的小结函数
);

掌握了以上基本语法信息后已经可以编写自定义聚合函数了。

参考于这篇文章:

Postgresql自定义聚合函数入门案例_pgsql自定义聚合函数_高铭杰的博客-CSDN博客

DROP AGGREGATE myavg(integer);
CREATE TABLE t_taxi(trip_id int, km numeric);

insert into t_taxi values (1, 3.4);
insert into t_taxi values (1, 5.3);
insert into t_taxi values (1, 2.9);
insert into t_taxi values (2, 9.3);
insert into t_taxi values (2, 1.6);
insert into t_taxi values (2, 4.3);

 trip_id | km  
---------+-----
       1 | 3.4
       1 | 5.3
       1 | 2.9
       2 | 9.3
       2 | 1.6
       2 | 4.3
————————————————

CREATE OR REPLACE FUNCTION taxi_accum (numeric, numeric, numeric)
RETURNS numeric AS
$$
BEGIN
    RAISE NOTICE 'prev:[%] curr:(%) outer:(%) return:(%)', $1, $2, $3, $1 + $2 * $3;
    RETURN $1 + $2 * $3;
END;
$$
LANGUAGE 'plpgsql';


CREATE OR REPLACE FUNCTION taxi_final (numeric)
RETURNS numeric AS
$$
BEGIN
    RAISE NOTICE 'final:(%) return:(%)', $1, round($1 + 5, -1);
    RETURN round($1 + 5, -1);
END;
$$
LANGUAGE 'plpgsql';

CREATE AGGREGATE taxi(numeric, numeric)
(
        SFUNC = taxi_accum,
        STYPE = numeric,
        FINALFUNC = taxi_final,
        INITCOND = 3.50
);


--测试
test=# SELECT  trip_id, taxi(km, 2.20), 3.50 + sum(km)*2.2 AS manual FROM t_taxi GROUP BY trip_id;
test-# /
NOTICE:  prev:[3.50] curr:(3.4) outer:(2.20) return:(10.980)
NOTICE:  prev:[10.980] curr:(5.3) outer:(2.20) return:(22.640)
NOTICE:  prev:[22.640] curr:(2.9) outer:(2.20) return:(29.020)--对trip_id为1的组进行SFUNC函数迭代计算
NOTICE:  prev:[3.50] curr:(9.3) outer:(2.20) return:(23.960)
NOTICE:  prev:[23.960] curr:(1.6) outer:(2.20) return:(27.480)
NOTICE:  prev:[27.480] curr:(4.3) outer:(2.20) return:(36.940)--对trip_id为2的组进行SFUNC函数迭代计算
NOTICE:  final:(29.020) return:(30)--对trip_id为1的组将SFUNC函数返回的结果(参数第一个值)进行最终计算
NOTICE:  final:(36.940) return:(40)--对trip_id为2的组将SFUNC函数返回的结果(参数第一个值)进行最终计算
 trip_id | taxi | manual
---------+------+--------
       1 |   30 |  29.02
       2 |   40 |  36.94
(2 rows)

Time: 1.775 ms

--可以看到基本的聚合函数(非并行)流程就是
--1,使用SFUNC函数对每组数据进行迭代计算
--2,每组数据计算完成后,使用FINALFUNC将每组的SFUNC结果

3,KES自定义聚合函数改写

使用plpgsql语法改写(对应上述oracle的sumc2函数)后:

--定义每行数据的迭代函数
CREATE OR REPLACE FUNCTION agg(v1 varchar,v2 varchar)
RETURNS varchar IMMUTABLE
AS 
$$
BEGIN
    if v1 is null or LENGTH(v1) = 0 then
        v1 := substr(v2, 0 , 2000) ;
    ELSIF v2 is null and v1 is not null then 
        v1 := substr(v1, 0 , 2000) ;
    ELSIF instr( v1, v2 ) = 0 then  ---如果是不包含关系(则拼接)
        v1 := substr(v1 || ',' || v2 , 0 , 2000) ;
    else
        v1 := substr(v1 , 0 , 2000) ;
    end if ;
    return v1;
end;
$$LANGUAGE 'plpgsql';

--定义每组的最终函数
CREATE OR REPLACE FUNCTION agg_final (varchar)
RETURNS varchar AS
$$
BEGIN
    RETURN $1;     ---本例子无需任何额外处理
END;
$$
LANGUAGE 'plpgsql';

---定义聚合函数
CREATE OR REPLACE AGGREGATE sumc2 (varchar)
(
    SFUNC = agg,   ---每组的自定义迭代函数
    STYPE = varchar,   ---聚合函数返回的数据类型
    FINALFUNC = agg_final,   ---每组的最终函数
    INITCOND =''   --INITCOND是第一次调用agg函数,给第一个参数的传值。
 );

对上述改写后的聚合函数进行基本功能的验证

kes测试:

--建表
CREATE table teachers (
  teacher_id number(8) not null,
  teacher_name varchar2 (40) not null,
  age number(2),  
  sal number(8,2) default 0,
  gender varchar2(10),
  title varchar2(20),
  POSITION  varchar2(20),
  department varchar2 (40) not null,
  constraint teach_ch_gender check ( gender in ('男','女')),
  constraint teach_ch_title check ( title in ('三级教师','二级教师','一级教师','高级教师','特级教师')),
  primary key(teacher_id,teacher_name) 
);
--建数据
insert  into teachers values(10001001,'陈思宇',46,15689.00,'男','特级教师','校长','校长室');
insert  into teachers values(10001002,'文强',44,14971.00,'男','特级教师','副校长','校长室');
insert  into teachers values(10001003,'吴玲',41,14571.00,'女','高级教师','办公室主任','办公室');
insert  into teachers values(10001004,'章丽',41,14121.00,'女','高级教师','教务处主任','教务处');
insert  into teachers values(10001005,'张志东',41,14121.00,'男','高级教师','财务处主任','财务处');
insert  into teachers values(10001006,'熊浩宇',49,14178.00,'女','一级教师','招生办主任','招生办');
insert  into teachers values(10001007,'朱雯',49,12008.00,'女','一级教师','招生办助理','招生办');
insert  into teachers values(10001008,'张志强',49,11982.00,'女','一级教师','财务处助理','财务处');
insert  into teachers values(10001009,'朱国斌',49,10987.00,'男','二级教师','财务处助理','财务处');

--查看表
test=# select * from teachers;
test-# /

 teacher_id | teacher_name | age |  sal  | gender | title  | position | department
------------+--------------+-----+----------+--------+----------+------------+------------
  10001001 | 陈思宇    | 46 | 15689.00 | 男   | 特级教师 | 校长    | 校长室
  10001002 | 文强     | 44 | 29942.00 | 男   | 特级教师 | 副校长   | 校长室
  10001003 | 吴玲     | 41 | 29142.00 | 女   | 高级教师 | 办公室主任 | 办公室
  10001004 | 章丽     | 41 | 28242.00 | 女   | 高级教师 | 教务处主任 | 教务处
  10001005 | 张志东    | 41 | 28242.00 | 男   | 高级教师 | 财务处主任 | 财务处
  10001006 | 熊浩宇    | 49 | 28356.00 | 女   | 一级教师 | 招生办主任 | 招生办
  10001007 | 朱雯     | 49 | 24016.00 | 女   | 一级教师 | 招生办助理 | 招生办
  10001008 | 张志强    | 49 | 23964.00 | 女   | 一级教师 | 财务处助理 | 财务处
  10001009 | 朱国斌    | 49 | 21974.00 | 男   | 二级教师 | 财务处助理 | 财务处

(9 rows)


--测试
test=# select age,sumc2(title) from teachers group by age;
test-# /
 age |       sumc2
-----+-------------------
  49 | 一级教师,二级教师
  44 | 特级教师
  46 | 特级教师
  41 | 高级教师
(4 rows)

Time: 1.517 ms

创建一个新的测试表,再次测试

drop table tt02;

create table tt02 (
  id int,
  name varchar2(200)
);

--kes:
declare 
  v int;
begin
   for i in 1..100000 loop
        select ceil(random()*10000 + 1) into v from dual;
        insert into tt02 values(v,'特级教师');
        select ceil(random()*10000 + 1) into v from dual;
        insert into tt02 values(v,'高级教师');
   end loop;
end;

--oracle:
declare 
  v int;
begin
  for i in 1..1000 loop
      select dbms_random.value(0,100000) into v from dual;
      insert into tt02 values(v,'特级教师');
      select dbms_random.value(0,100000) into v from dual;
      insert into tt02 values(v,'高级教师');
  end loop;
end;

test=# select * from tt02;

 id |  name
----+----------
 1 | 特级教师
 2 |
 3 | 特级教师
 4 | 中级教师
 5 | 特级教师
 6 |
 7 | 特级教师
 8 | 中级教师
(8 rows)

test=# select sumc2(name) from tt02;
test-# /

    sumc2
-------------------
 特级教师,中级教师

(1 row)

故此测试结果和oracle一致,符合基本的预期

注意:以上代码内容未对并行条件下进行考虑,后期将对齐进行讲解

标签:聚合,函数,自定义,--,into,Kingbase,values,ES
From: https://www.cnblogs.com/kingbase/p/17561077.html

相关文章

  • kingbaseES sql 优化技巧汇总
    1、整体思路针对业务系统的出现的慢sql我们的优化步骤大概分为以下几步1、识别高负载语句2、收集性能相关的数据3、确定性能问题产生的原因4、实施优化手段下面我们针对这几个步骤展开进行讲解1、识别高负载语句金仓数据库kingbaseES针对满语句识别有以下几个工具•s......
  • kingbaseES 优化之操作系统瓶颈排查
    针对操作系统性能瓶颈的判断和排查是数据库优化工作的一项重要技能,尤其是针对实例整体优化操作系统的性能瓶颈排查无外乎四个方面CPU、内存、磁盘、网络针对这四个方面整理了一些相关心得和大家分享。在判断系统瓶颈之前首先我们要知道操作系统资源的极限值在哪里收集系统信......
  • kingbaseES 优化之数据库瓶颈排查
    针对数据库的性能瓶颈排查方法分为两个层次1、实例级别性能问题排查2、语句级别性能问题排查实例级别实例级别性能问题排查用来分析数据库实例整体是否存在性能瓶颈,然后根据排除出的疑似问题进行实例级别参数的优化。使用场景包括1、压测场景下数据库整体优化2、上线之前数......
  • Kingbase ES 函数返回-return语句
    文章概要:本文在https://www.cnblogs.com/kingbase/p/15703611.html一文的基础上总结了KingbaseES中函数能支持的return语句,整体上兼容oracle的基础上,也和PG语法一样。同时列举了sqlserevr表值函数和代码故障案例。一,关于return语句有5个return语句可以用来从KES函数中返回数......
  • kingbaseES V8R3集群运维案例之---集群部署前后ssh端口修改
    kingbaseESV8R3集群运维案例之---集群部署前后ssh端口修改案例说明:kingbaseESV8R3集群部署读写分离的集群是使用ssh的默认端口(22)部署,当改为非默认端口时,在部署中或部署后会因kingbasecluster脚本ssh的连接而失败,现提出以下解决方案。适用版本:KingbaseESV8R31......
  • 使用MessageFormatter.format替代 String.format
    使用MessageFormatter.format替代String.format现有的J2EE项目中基本都会引用日志框架,刚好日志框架中有对应的工具类可以使用,对数据进行格式化:importorg.slf4j.helpers.MessageFormatter;Stringformat1=String.format("%s/%s",1,2);S......
  • presto/trino QueryStatistics 数据来源分析
    QueryStatisticsQueryStats来自stageStats累加来自taskStats累加PipelineStatsdriverStatsOperatorStatsinputOperatorPageSourceOperatorTableScanOperatorWorkProcessorPipelineSourceOperatorWorkProcessorSourceOperatorAdapter......
  • KingbaseES V8R6运维案例之---数据库resetwal后启动失败
    KingbaseESV8R6运维案例之---数据库resetwal后启动失败案例说明:KingbaseESV8R6集群触发failover切换后,原主库自动recovery失败,现在需要将原主库启动为单实例的数据库运行,在执行了resetwal后,启动数据库失败。sys_log记录以下故障信息:适用版本:KingbaseESV8R6......
  • KingbaseES V8R6集群运维案例之---访问系统表unrecognized token- false故障
    KingbaseESV8R6集群运维案例之---访问系统表‘unrecognizedtoken:"false"’故障案例说明:KingbaseESV8R6集群在升级补丁后,主备库访问系统表出现‘unrecognizedtoken:"false"’故障,如下图所示:适用版本:KingbaseESV8R3/R6一、问题分析1、连接数据库执行系统表访问(如......
  • KingbaseES V8R6集群运维案例--cluster模式备份sys_backup.sh init故障
    KingbaseESV8R6集群运维案例--cluster模式备份sys_backup.shinit故障案例说明:通过脚本方式部署KingbaseESV8R6集群后,在‘cluster’模式备份,执行sys_backup.shinit时,出现“cannotcontain//for”log-path"option"错误,但是在‘single’模式下备份,无此错误。故障信息......