南大通用GBase 8s_GROUP BY支援標量函式和表示式問題詳解

CallMeJasonGao發表於2020-09-28

1        概述

為與主流資料庫相容, GBase 8s 在很多國產化替代專案中做了很多努力,其中, Group By 語句對標量函式及表示式的支援問題較為典型,這篇文章會詳細闡述一下。

2        問題現狀

2.1     現狀描述

在某國產化替代專案現場出現如下場景: 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') ;

 

2.2     問題分析

在某主流資料庫中對 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: 均不支援。

2.3     問題總結

經分析測試,主流資料庫對 Group By 子句存在標量函式和表示式的場景支援較好。

GBase 8s 資料庫會加強相容性方面的功能支援,以支援上述場景,降低從主流資料庫遷移到 GBase 8s 資料庫的適配難度,提供更強大的相容能力。

3        解決方案

為解決國產化替代過程中出現的較多相容性要求,涵蓋絕大多數 Group By 語句相容性場景, GBase 8s Group By 語句在現有基礎上逐步加強對標量表示式的支援,可按照以下方式解決:

1)         若投影列中存在 Group By 子句中的標量表示式,則必須與 Group By 子句中的標量表示式保持一致。

2)         標量表示式包括:

Ø   標量函式,標量函式的引數包含 from 子句中表的列;

Ø   算術表示式,算術表示式中參與運算的元素必須包含 from 子句中表的列;

Ø   標量巢狀函式,巢狀層級與現有 GBase 8s 規則保持一致;

Ø   其他表示式情況與現有系統保持一致。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69980453/viewspace-2724866/,如需轉載,請註明出處,否則將追究法律責任。

相關文章