为与主流数据库兼容, GBase 8s 在很多国产化替代项目中做了很多努力,其中, Group By 语句对标量函数及表达式的支持问题较为典型,这篇文章会详细阐述一下。
在某国产化替代项目现场出现如下场景: Group By 子句需要支持 to_char 函数分组(包含不在投影列中的字段)。在这种场景下, GBase 8s 会报错 “SQL 错误【 ErrorCode : -201 】【 SQLState : 42000 】: A syntax error has occurred.” 。如下所示:
源 SQL :
select
count(distinct(t.col4)) as psr_num,
1 as defaulVal,
t.col2
from test t
where t.col1 > 10
group by t.col2, to_char(t.col5,'YYYY-MM-DD') ;
在某主流数据库中对 Group By 语句对标量函数及表达式支持情况进行测试分析,过程如下。
a. 测试表 table1 结构 :
|
col1 |
col2 |
col3 |
col4 |
col5 |
col6 |
|
1 |
2 |
3 |
1 |
2019-10-10 12:12:12 |
2019-10-11 12:12:12 |
b. 测试过程:
l 标量函数
Ø 测试 SQL :
标量函数:
SQL1: select col2, to_char(col5,'YYYY-MM-DD HH:MM:SS'),count(distinct(col4)) from table1 group by col2, to_char(col5,'YYYY-MM-DD HH:MM:SS');
SQL2: select abs(col2), count(distinct(col4)) from table1 group by abs(col2), col1;
SQL3: select to_char(col5,'YYYY') from table1 group by to_char(col5,'YYYY-MM');
SQL4: select to_char(col2) from table1 group by abs(col2);
SQL5: select col3+abs(col2), count(distinct(col4)) from table1 group by abs(col2), col3;
嵌套函数:
SQL6: select sum(avg(abs(col2))) from table1 group by nvl(col2,col3);
SQL7: select avg(sum(avg(abs(col2)))) from table1 group by nvl(col2,col3);
SQL8: select to_char(abs(abs(col2))) from table1 group by to_char(abs(abs(col2)));
Ø 测试结果:
SQL1-2 、 SQL5 语句执行成功, SQL3-4 语句执行失败,说明标量函数在 select 投影列中单独存在时需与 group by 语句中出现的标量函数保持一致,包括函数名称及参数。
SQL6 、 SQL8 语句执行成功, SQL7 语句执行失败,说明 select 投影列中聚合函数最多嵌套两层,而标量函数可无限嵌套,但投影列与 group by 语句中嵌套的标量函数必须保持一致。
l 表达式
Ø 测试 SQL :
算术表达式
SQL1: select col1+col2, count(distinct(col4)) from table1 group by col2+col1, col3;
SQL2: select 1+col2, count(distinct(col4)) from table1 group by col2+1, col3;
SQL3: select col2+1+col3, count(distinct(col4)) from table1 group by col2+1, col3;
SQL4: select col2+col3+1, count(distinct(col4)) from table1 group by col2+1, col3;
比较表达式:
SQL5: select count(col2) from table1 group by col2>1;
逻辑表达式:
SQL6: select count(col2) from table1 group by col2>1 and col2<10;
按位表达式:
SQL7: select count(col2) from table1 group by col2 | col3;
Ø 测试结果:
SQL1-3: 主流数据库均支持。
SQL4-7: 均不支持。
说明 group by 语句后的表达式仅支持算术表达式且遵循交换律,对比较表达式、逻辑表达式和按位表达式并不提供支持。
l 标量函数 + 表达式
Ø 测试 SQL :
SQL1: select 1+abs(col2), count(distinct(col4)) from table1 group by abs(col2)+1, col3;
SQL2: select 1+abs(col2)+col3, count(distinct(col4)) from table1 group by abs(col2)+1, col3;
SQL3: select abs(col2+1) from table1 group by abs(1+col2);
SQL4: select abs(col2)+col3 from table1 group by col3+abs(col2);
SQL5: select sum(abs(col2+1)) from table1 group by 1+col2;
SQL6: select abs(col2+col3+1) from table1 group by abs(1+col2+col3);
SQL7: select abs(col2)+col3+1 from table1 group by abs(col2)+1, col3;
SQL8: select abs(col2-1) from table1 group by abs(1-col2);
Ø 测试结果:
SQL1-5: 支持。
SQL6-8: 均不支持。
经分析测试,主流数据库对 Group By 子句存在标量函数和表达式的场景支持较好。
GBase 8s 数据库会加强兼容性方面的功能支持,以支持上述场景,降低从主流数据库迁移到 GBase 8s 数据库的适配难度,提供更强大的兼容能力。
为解决国产化替代过程中出现的较多兼容性要求,涵盖绝大多数 Group By 语句兼容性场景, GBase 8s 的 Group By 语句在现有基础上逐步加强对标量表达式的支持,可按照以下方式解决:
1) 若投影列中存在 Group By 子句中的标量表达式,则必须与 Group By 子句中的标量表达式保持一致。
2) 标量表达式包括:
Ø 标量函数,标量函数的参数包含 from 子句中表的列;
Ø 算术表达式,算术表达式中参与运算的元素必须包含 from 子句中表的列;
Ø 标量嵌套函数,嵌套层级与现有 GBase 8s 规则保持一致;
Ø 其他表达式情况与现有系统保持一致。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69980453/viewspace-2724866/ ,如需转载,请注明出处,否则将追究法律责任。