MaxCompute自身預置了諸多函數,可以滿足大部分業務情境的資料處理需求。本文為您介紹MaxCompute提供的函數類型及函數使用相關說明。
背景資訊
使用MaxCompute內建函數過程中,需要注意的事項請參見注意事項。
MaxCompute預置的函數類型如下。
函數類型 | 說明 |
支援處理DATE、DATETIME、TIMESTAMP等日期類型資料,實現加減日期、計算日期差值、提取日期欄位、擷取目前時間、轉換日期格式等業務處理能力。 | |
支援處理BIGINT、DOUBLE、DECIMAL、FLOAT等數實值型別資料,實現轉換進位、數學運算、四捨五入、擷取隨機數等業務處理能力。 | |
支援在指定的開窗列中,實現求和、求最大最小值、求平均值、求中間值、數值排序、數值位移、抽樣等業務處理能力。 | |
支援將多條輸入記錄彙總成一條輸出值,實現求和、求平均值、求最大最小值、求平均值、參數彙總、字串串連等業務處理能力。 | |
支援處理STRING類型字串,實現截取字串、替換字串、尋找字串、轉換大小寫、轉換字串格式等業務處理能力。 | |
支援處理MAP、ARRAY、STRUCT及JSON類型資料,實現去重元素、彙總元素、元素排序、合并元素等業務處理能力。 | |
支援處理STRING、BINARY類型的表資料,實現加密、解密等業務處理能力。 | |
除上述函數之外,提供支援其他業務情境的函數。 |
MaxCompute內建函數的典型案例、錯誤碼和常見問題請參見ROUND函數精度問題案例、實現GROUP_CONCAT函數能力案例、內建函數常見錯誤碼和內建函數常見問題。
注意事項
在使用內建函數時,需要注意:
內建函數的入參類型、入參數量、函數格式必須滿足函數文法要求,否則MaxCompute無法成功解析函數,SQL運行會報錯。
如果內建函數的入參涉及2.0新資料類型(例如TINYINT、SMALLINT、INT、FLOAT、VARCHAR、TIMESTAMP或BINARY),您需要開啟2.0新資料類型開關,否則運行會報錯。開關開啟檔案如下:
Session層級:您需要在SQL語句前加上
set odps.sql.type.system.odps2=true;
,與SQL語句一起提交執行。該配置僅對本次啟動並執行SQL有效。Project層級:Project Owner可根據需要對MaxCompute專案進行設定,等待10~15分鐘後才會生效。該配置對後續啟動並執行所有SQL有效。
setproject odps.sql.type.system.odps2=true;
當MaxCompute專案開啟2.0新資料類型開關時,部分隱式類型轉換會被禁用,包括STRING轉換為BIGINT、STRING轉換為DATETIME、DOUBLE轉換為BIGINT、DECIMAL轉換為DOUBLE、DECIMAL轉換為BIGINT,都有精度損失或報錯的風險。此時,您可以通過CAST函數執行強制轉換解決該問題,或關閉2.0新資料類型開關。
當自訂函數的名稱與內建函數的名稱相同時,自訂函數會覆蓋同名的內建函數。例如,MaxCompute中存在一個名稱為CONCAT的自訂函數,則系統預設會調用自訂的CONCAT,不會調用內建函數CONCAT。如果您希望調用內建函數,需要在內建函數前增加
::
符號,例如select ::concat('ab', 'c');
。如果MaxCompute專案的全域屬性設定不同,內建函數啟動並執行結果可能會不一致,您可以通過
setproject;
命令查看專案的全域屬性資訊。
各類型函數與開源函數的對照關係,請參見與Hive、MySQL、Oracle內建函數對照表。
日期函數
MaxCompute SQL提供了如下日期函數,您可以根據實際需要選擇合適的日期函數,完成日期計算、日期轉換。
函數 | 功能 |
按照指定的單位和幅度修改日期值。 | |
按照指定的幅度增減天數,與 | |
將日期值轉換為指定格式的字串。 | |
按照指定的幅度增減天數,與 | |
計算兩個日期的差值並按照指定的單位表示。 | |
提取日期中符合指定時間單位的欄位值。 | |
提取日期按照指定時間單位截取後的值。 | |
將數字型的UNIX值轉換為日期值。 | |
擷取當前系統時間。 | |
判斷一個日期文字能否根據指定的格式串轉換為一個日期值。 | |
擷取日期所在月的最後一天。 | |
將指定格式的字串轉換為日期值。 | |
將日期按照指定格式轉換為字串。 | |
將日期轉換為整型的UNIX格式的日期值。 | |
返回日期值是當前周的第幾天。 | |
返回日期值位於當年的第幾周。 | |
計算日期值增加指定月數後的日期。 | |
返回當前TIMESTAMP類型的時間戳記。 | |
返回當前系統的時區資訊。 | |
返回日期值的天。 | |
返回日部分的值。 | |
返回日期的星期值。 | |
返回日期是當年中的第幾天。 | |
擷取日期TIMESTAMP中指定單位的部分。 | |
將一個UTC時區的時間戳記轉換為一個指定時區的時間戳記。 | |
返回日期小時部分的值。 | |
返回日期值所在月份的最後一天日期。 | |
返回日期分鐘部分的值。 | |
返回日期值所屬月份。 | |
返回指定日期值間的月數。 | |
返回大於日期值且與指定周相匹配的第一個日期。 | |
返回日期值所屬季度。 | |
返回日期秒數部分的值。 | |
將指定日期轉換為以毫秒為單位的UNIX時間戳記。 | |
返回日期值的年。 |
數學函數
MaxCompute SQL提供了如下數學函數供您在開發過程中使用,您可以根據實際需要選擇合適的數學函數,進行資料計算、資料轉換相關操作。
取餘數計算等更多計算請參見算術運算子。
函數 | 功能 |
計算絕對值。 | |
計算反餘弦值。 | |
計算反正弦值。 | |
計算反正切值。 | |
計算expr1/expr2的反正切函數。 | |
計算向上取整值。 | |
計算進位轉換值。 | |
計算餘弦值。 | |
計算雙曲餘弦值。 | |
計算餘切值。 | |
計算指數值。 | |
計算向下取整值。 | |
判斷運算式的值是否是NaN。 | |
計算自然對數。 | |
計算log對數值。 | |
返回運算式的負值。 | |
返回運算式的值。 | |
計算冪值。 | |
返回隨機數。 | |
返回四捨五入到指定小數點位置的值。 | |
計算正弦值。 | |
計算雙曲正弦值。 | |
計算平方根。 | |
計算正切值。 | |
計算雙曲正切值。 | |
返回截取到指定小數點位置的值。 | |
計算二進位代碼值。 | |
計算立方根值。 | |
計算皮爾遜係數。 | |
將弧度轉換為角度。 | |
返回e的值。 | |
計算階乘值。 | |
將數字轉化為指定格式的字串。 | |
返回整數或字串的十六進位格式。 | |
計算以2為底的對數。 | |
計算以10為底的對數。 | |
返回π的值。 | |
將角度轉換為弧度。 | |
返回輸入參數的符號。 | |
計算按位左移值。 | |
計算按位右移值。 | |
計算無符號按位右移值。 | |
返回十六進位字串所代表的字串。 | |
返回指定欄位值落入的分組編號。 |
視窗函數
MaxCompute SQL提供了如下視窗函數,使用視窗函數對指定開窗列的資料靈活地進行分析處理工作。
函數 | 功能 |
計算行號。從1開始遞增。 | |
計算排名。排名可能不連續。 | |
計算排名。排名是連續的。 | |
計算排名。輸出百分比格式。 | |
計算累計分布。 | |
將資料順序切分成N等份,返回資料所在等份的編號(從1到N)。 | |
取當前行往前(朝分區頭部方向)第N行資料的值。 | |
取當前行往後(朝分區尾部方向)第N行資料的值。 | |
取當前行所對應視窗的第一條資料的值。 | |
取當前行所對應視窗的最後一條資料的值。 | |
取當前行所對應視窗的第N條資料的值。 | |
使用者隨機抽樣。返回True表示該行資料被抽中。 | |
計算視窗中的記錄數。 | |
計算視窗中的最小值。 | |
計算視窗中的最大值。 | |
對視窗中的資料求平均值。 | |
對視窗中的資料求和。 | |
計算視窗中的中位元。 | |
計算總體標準差。是STDDEV_POP的別名。 | |
計算樣本標準差。 |
視窗函數文法
視窗函數的文法聲明如下。
<function_name>([distinct][<expression> [, ...]]) over (<window_definition>) <function_name>([distinct][<expression> [, ...]]) over <window_name>
expression:函數格式,具體格式以實際函數文法為準。
windowing_definition:視窗定義。詳細文法格式請參見windowing_definition部分。
window_name:視窗名稱。您可以使用
window
關鍵字自訂視窗,為windowing_definition定義名稱。自訂語句(named_window_def)如下:window <window_name> as (<window_definition>)
自訂語句在SQL中的位置如下:
select ... from ... [where ...] [group by ...] [having ...] named_window_def [order by ...] [limit ...]
windowing_definition
windowing_definition的文法聲明如下。
--partition_clause: [partition by <expression> [, ...]] --orderby_clause: [order by <expression> [asc|desc][nulls {first|last}] [, ...]] [<frame_clause>]
在SELECT語句中加入視窗函數,計算視窗函數的結果時,資料會按照視窗定義中的
partition by
和order by
語句進行分區和排序。如果沒有partition by
語句,則僅有一個分區,包含全部資料。如果沒有order by
語句,則分區內的資料會按照任意順序排布,最終產生一個確定的資料流。之後對於每一行資料(當前行),會按照視窗定義中的frame_clause
從資料流中截取一段資料,構成當前行的視窗。視窗函數會根據視窗中包含的資料,計算得到視窗函數針對當前行對應的輸出結果。partition by <expression> [, ...]:可選。指定分區。分區列的值相同的行被視為在同一個視窗內。詳細格式請參見表操作。
order by <expression> [asc|desc][nulls {first|last}] [, ...]:可選。指定資料在一個視窗內如何排序。
說明當遇到相同的
order by
值時,排序結果不穩定。為減少隨機性,應當儘可能保持order by
值的唯一性。frame_clause:可選。用於確定資料邊界,更多frame_clause資訊,請參見frame_clause部分。
frame_clause
frame_clause的文法聲明如下。
--格式一。 {ROWS|RANGE|GROUPS} <frame_start> [<frame_exclusion>] --格式二。 {ROWS|RANGE|GROUPS} between <frame_start> and <frame_end> [<frame_exclusion>]
frame_clause是一個閉區間,用於確定資料邊界,包含frame_start和frame_end位置的資料行。
ROWS|RANGE|GROUPS:必填。frame_clause的類型,各類型的frame_start和frame_end實現規則不相同。其中:
ROWS類型:通過資料行數確定資料邊界。
RANGE類型:通過比較
order by
列值的大小關係來確定資料邊界。一般在視窗定義中會指定order by
,未指定order by
時,一個分區中的所有資料行具有相同的order by
列值。NULL與NULL被認為是相等的。GROUPS:一個分區中所有具有相同
order by
列值的資料群組成一個GROUP。未指定order by
時,分區中的所有資料群組成一個GROUP。NULL與NULL被認為是相等的。
frame_start、frame_end:表示視窗的起始和終止邊界。frame_start必填。frame_end可選,省略時預設值為CURRENT ROW。
frame_start確定的位置必須在frame_end確定的位置的前面,或者等於frame_end的位置,即frame_start相比frame_end更靠近分區頭部。分區頭部是指資料按視窗定義中的
order by
語句排序之後第1行資料的位置。ROWS、RANGE、GROUPS類型對應的取值範圍及實現邏輯如下。frame_clause類型
frame_start/frame_end取值
說明
ROWS、RANGE、GROUPS
UNBOUNDED PRECEDING
表示分區的第一行,從1開始計數。
UNBOUNDED FOLLOWING
表示分區的最後一行。
ROWS
CURRENT ROW
指當前行的位置。每一行資料都會對應一個視窗函數的結果值,當前行是指在給哪一行資料計算視窗函數的結果。
offset PRECEDING
指從當前行位置,向分區頭部位置移動
offset
行的位置。例如0 PRECEDING
指當前行,1 PRECEDING
指前一行。offset
必須為非負整數。offset FOLLOWING
指從當前行位置,向分區尾部移動
offset
行的位置。例如0 FOLLOWING
指當前行,1 FOLLOWING
指下一行。offset
必須為非負整數。RANGE
CURRENT ROW
作為frame_start時,指第一條與當前行具有相同
order by
列值的資料的位置。作為frame_end時,指最後一條與當前行具有相同
order by
列值的資料的位置。
offset PRECEDING
frame_start和frame_end的位置與
order by
的順序相關。假設視窗按照X進行排序,Xi表示第i行資料對應的X值,Xc表示當前行資料對應X值。位置說明如下:當
order by
為升序時:frame_start:指第一條滿足
Xc - Xi <= offset
資料的位置。frame_end:指最後一條滿足
Xc - Xi >= offset
資料的位置。
當
order by
為降序時:frame_start:指第一條滿足
Xi - Xc <= offset
資料的位置。frame_end:指最後一條滿足
Xi - Xc >= offset
資料的位置。
order by
的列支援的資料類型為:TINYINT、SMALLINT、INT、BIGINT、FLOAT、DOUBLE、DECIMAL、DATETIME、DATE、TIMESTAMP。日期類型資料的
offset
文法如下:N
:表示N天或N秒。非負整數。對於DATETIME和TIMESTAMP,表示N秒;對於DATE,表示N天。interval 'N' {YEAR\MONTH\DAY\HOUR\MINUTE\SECOND}
:表示N年/月/日/小時/分鐘/秒。例如INTERVAL '3' YEAR
表示3年。INTERVAL 'N-M' YEAR TO MONTH
:表示N年M月。例如INTERVAL '1-3' YEAR TO MONTH
表示1年3個月。INTERVAL 'D[ H[:M[:S[:N]]]]' DAY TO SECOND
:表示D天H小時M分鐘S秒N納秒。例如INTERVAL '1 2:3:4:5' DAY TO SECOND
表示1天2小時3分鐘4秒5納秒。
offset FOLLOWING
frame_start和frame_end的位置與
order by
的順序相關。假設視窗按照X進行排序,Xi表示第i行資料對應的X值,Xc表示當前行資料對應X值。位置說明如下:當
order by
為升序時:frame_start:指第一條滿足
Xi - Xc >= offset
資料的位置。frame_end:指最後一條滿足
Xi - Xc <= offset
資料的位置。
當
order by
為降序時:frame_start:指第一條滿足
Xc - Xi >= offset
資料的位置。frame_end:指最後一條滿足
Xc - Xi <= offset
資料的位置。
GROUPS
CURRENT ROW
作為frame_start時,指當前行所屬GROUP的第一條資料。
作為frame_end時,指當前行所屬GROUP的最後一行資料。
offset PRECEDING
作為frame_start時,指從當前行所屬GROUP開始,朝分區頭部移動
offset
個GROUP之後,所在GROUP的第一條資料的位置。作為frame_end時,指從當前行所屬GROUP開始,朝分區頭部移動
offset
個GROUP之後,所在GROUP的最後一條資料的位置。
說明frame_start不能設定為UNBOUNDED FOLLOWING,frame_end不能設定為UNBOUNED PRECEDING。
offset FOLLOWING
作為frame_start時,指從當前行所屬GROUP開始,朝分區尾部移動
offset
個GROUP之後,所在GROUP的第一條資料的位置。作為frame_end時,指從當前行所屬GROUP開始,朝分區尾部移動
offset
個GROUP之後,所在GROUP的最後一條資料的位置。
說明frame_start不能設定為UNBOUNDED FOLLOWING,frame_end不能設定為UNBOUNED PRECEDING。
frame_exclusion:可選。用於從視窗中剔除一部分資料。取值範圍如下:
EXCLUDE NO OTHERS:表示不剔除任何資料。
EXCLUDE CURRENT ROW:表示剔除當前行。
EXCLUDE GROUP:表示剔除整個GROUP,即分區中與當前行具有相同
order by
值的所有資料。EXCLUDE TIES:表示剔除整個GROUP,但保留當前行。
預設frame_clause
未顯示設定frame_clause時,MaxCompute會使用預設的frame_clause來決定視窗所包含資料的邊界。預設的frame_clause為:
當開啟Hive相容模式(
set odps.sql.hive.compatible=true;
)時,預設的frame_clause如下,與大部分SQL系統相同。RANGE between UNBOUNDED PRECEDING and CURRENT ROW EXCLUDE NO OTHERS
當關閉Hive相容模式(
set odps.sql.hive.compatible=false;
),同時視窗定義中指定了order by
語句,且視窗函數為AVG、COUNT、MAX、MIN、STDDEV、STEDEV_POP、STDDEV_SAMP或SUM時,會使用ROWS類型的預設frame_clause。ROWS between UNBOUNDED PRECEDING and CURRENT ROW EXCLUDE NO OTHERS
視窗邊界樣本
假設表tbl結構為
pid: bigint, oid: bigint, rid: bigint
,表中包含如下資料:+------------+------------+------------+ | pid | oid | rid | +------------+------------+------------+ | 1 | NULL | 1 | | 1 | NULL | 2 | | 1 | 1 | 3 | | 1 | 1 | 4 | | 1 | 2 | 5 | | 1 | 4 | 6 | | 1 | 7 | 7 | | 1 | 11 | 8 | | 2 | NULL | 9 | | 2 | NULL | 10 | +------------+------------+------------+
您可以將如下SQL語句中的
...
替換為視窗定義語句windowing_definition來展示每一條資料所對應的視窗包含的資料列表:說明Window列為NULL時,不包含任何資料。
ROW類型視窗
視窗定義1
partition by pid order by oid ROWS between UNBOUNDED PRECEDING and CURRENT ROW --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid ROWS between UNBOUNDED PRECEDING and CURRENT ROW) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | [1] | | 1 | NULL | 2 | [1, 2] | | 1 | 1 | 3 | [1, 2, 3] | | 1 | 1 | 4 | [1, 2, 3, 4] | | 1 | 2 | 5 | [1, 2, 3, 4, 5] | | 1 | 4 | 6 | [1, 2, 3, 4, 5, 6] | | 1 | 7 | 7 | [1, 2, 3, 4, 5, 6, 7] | | 1 | 11 | 8 | [1, 2, 3, 4, 5, 6, 7, 8] | | 2 | NULL | 9 | [9] | | 2 | NULL | 10 | [9, 10] | +------------+------------+------------+--------+
視窗定義2
partition by pid order by oid ROWS between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid ROWS between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | [1, 2, 3, 4, 5, 6, 7, 8] | | 1 | NULL | 2 | [1, 2, 3, 4, 5, 6, 7, 8] | | 1 | 1 | 3 | [1, 2, 3, 4, 5, 6, 7, 8] | | 1 | 1 | 4 | [1, 2, 3, 4, 5, 6, 7, 8] | | 1 | 2 | 5 | [1, 2, 3, 4, 5, 6, 7, 8] | | 1 | 4 | 6 | [1, 2, 3, 4, 5, 6, 7, 8] | | 1 | 7 | 7 | [1, 2, 3, 4, 5, 6, 7, 8] | | 1 | 11 | 8 | [1, 2, 3, 4, 5, 6, 7, 8] | | 2 | NULL | 9 | [9, 10] | | 2 | NULL | 10 | [9, 10] | +------------+------------+------------+--------+
視窗定義3
partition by pid order by oid ROWS between 1 FOLLOWING and 3 FOLLOWING --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid ROWS between 1 FOLLOWING and 3 FOLLOWING) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | [2, 3, 4] | | 1 | NULL | 2 | [3, 4, 5] | | 1 | 1 | 3 | [4, 5, 6] | | 1 | 1 | 4 | [5, 6, 7] | | 1 | 2 | 5 | [6, 7, 8] | | 1 | 4 | 6 | [7, 8] | | 1 | 7 | 7 | [8] | | 1 | 11 | 8 | NULL | | 2 | NULL | 9 | [10] | | 2 | NULL | 10 | NULL | +------------+------------+------------+--------+
視窗定義4
partition by pid order by oid ROWS between UNBOUNDED PRECEDING and CURRENT ROW EXCLUDE CURRENT ROW --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid ROWS between UNBOUNDED PRECEDING and CURRENT ROW EXCLUDE CURRENT ROW) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | NULL | | 1 | NULL | 2 | [1] | | 1 | 1 | 3 | [1, 2] | | 1 | 1 | 4 | [1, 2, 3] | | 1 | 2 | 5 | [1, 2, 3, 4] | | 1 | 4 | 6 | [1, 2, 3, 4, 5] | | 1 | 7 | 7 | [1, 2, 3, 4, 5, 6] | | 1 | 11 | 8 | [1, 2, 3, 4, 5, 6, 7] | | 2 | NULL | 9 | NULL | | 2 | NULL | 10 | [9] | +------------+------------+------------+--------+
視窗定義5
partition by pid order by oid ROWS between UNBOUNDED PRECEDING and CURRENT ROW EXCLUDE GROUP --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid ROWS between UNBOUNDED PRECEDING and CURRENT ROW EXCLUDE GROUP) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | NULL | | 1 | NULL | 2 | NULL | | 1 | 1 | 3 | [1, 2] | | 1 | 1 | 4 | [1, 2] | | 1 | 2 | 5 | [1, 2, 3, 4] | | 1 | 4 | 6 | [1, 2, 3, 4, 5] | | 1 | 7 | 7 | [1, 2, 3, 4, 5, 6] | | 1 | 11 | 8 | [1, 2, 3, 4, 5, 6, 7] | | 2 | NULL | 9 | NULL | | 2 | NULL | 10 | NULL | +------------+------------+------------+--------+
視窗定義6
partition by pid order by oid ROWS between UNBOUNDED PRECEDING and CURRENT ROW EXCLUDE TIES --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid ROWS between UNBOUNDED PRECEDING and CURRENT ROW EXCLUDE TIES) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | [1] | | 1 | NULL | 2 | [2] | | 1 | 1 | 3 | [1, 2, 3] | | 1 | 1 | 4 | [1, 2, 4] | | 1 | 2 | 5 | [1, 2, 3, 4, 5] | | 1 | 4 | 6 | [1, 2, 3, 4, 5, 6] | | 1 | 7 | 7 | [1, 2, 3, 4, 5, 6, 7] | | 1 | 11 | 8 | [1, 2, 3, 4, 5, 6, 7, 8] | | 2 | NULL | 9 | [9] | | 2 | NULL | 10 | [10] | +------------+------------+------------+--------+
對比本樣本與前一個樣本中
rid
為2、4、10的window
結果,可以觀察到EXCLUDE CURRENT ROW與EXCLUDE GROUP的差異,即對於EXCLUDE GROUP,同一個分區中(pid
相等),與當前行為相同oid
的資料都被剔除了。
RANGE類型視窗
視窗定義1
partition by pid order by oid RANGE between UNBOUNDED PRECEDING and CURRENT ROW --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid RANGE between UNBOUNDED PRECEDING and CURRENT ROW) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | [1, 2] | | 1 | NULL | 2 | [1, 2] | | 1 | 1 | 3 | [1, 2, 3, 4] | | 1 | 1 | 4 | [1, 2, 3, 4] | | 1 | 2 | 5 | [1, 2, 3, 4, 5] | | 1 | 4 | 6 | [1, 2, 3, 4, 5, 6] | | 1 | 7 | 7 | [1, 2, 3, 4, 5, 6, 7] | | 1 | 11 | 8 | [1, 2, 3, 4, 5, 6, 7, 8] | | 2 | NULL | 9 | [9, 10] | | 2 | NULL | 10 | [9, 10] | +------------+------------+------------+--------+
CURRENT ROW作為frame_end時,取與當前行具有相同
order by
值oid
的最後一條資料,因此rid
為1的記錄的window
結果為[1, 2]。視窗定義2
partition by pid order by oid RANGE between CURRENT ROW and UNBOUNDED FOLLOWING --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid RANGE between CURRENT ROW and UNBOUNDED FOLLOWING) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | [1, 2, 3, 4, 5, 6, 7, 8] | | 1 | NULL | 2 | [1, 2, 3, 4, 5, 6, 7, 8] | | 1 | 1 | 3 | [3, 4, 5, 6, 7, 8] | | 1 | 1 | 4 | [3, 4, 5, 6, 7, 8] | | 1 | 2 | 5 | [5, 6, 7, 8] | | 1 | 4 | 6 | [6, 7, 8] | | 1 | 7 | 7 | [7, 8] | | 1 | 11 | 8 | [8] | | 2 | NULL | 9 | [9, 10] | | 2 | NULL | 10 | [9, 10] | +------------+------------+------------+--------+
視窗定義3
partition by pid order by oid RANGE between 3 PRECEDING and 1 PRECEDING --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid RANGE between 3 PRECEDING and 1 PRECEDING) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | [1, 2] | | 1 | NULL | 2 | [1, 2] | | 1 | 1 | 3 | NULL | | 1 | 1 | 4 | NULL | | 1 | 2 | 5 | [3, 4] | | 1 | 4 | 6 | [3, 4, 5] | | 1 | 7 | 7 | [6] | | 1 | 11 | 8 | NULL | | 2 | NULL | 9 | [9, 10] | | 2 | NULL | 10 | [9, 10] | +------------+------------+------------+--------+
order by
值oid
為NULL的行,對於offset {PRECEDING|FOLLOWING}
,只要offset
不為UNBOUNDED,則作為frame_start,指向分區中第一條order by
值為NULL的資料;作為frame_end,指向最後一條order by
值為NULL的資料。
GROUPS類型視窗
視窗定義如下:
partition by pid order by oid GROUPS between 2 PRECEDING and CURRENT ROW --SQL語句如下。 select pid, oid, rid, collect_list(rid) over(partition by pid order by oid GROUPS between 2 PRECEDING and CURRENT ROW) as window from tbl;
返回結果如下:
+------------+------------+------------+--------+ | pid | oid | rid | window | +------------+------------+------------+--------+ | 1 | NULL | 1 | [1, 2] | | 1 | NULL | 2 | [1, 2] | | 1 | 1 | 3 | [1, 2, 3, 4] | | 1 | 1 | 4 | [1, 2, 3, 4] | | 1 | 2 | 5 | [1, 2, 3, 4, 5] | | 1 | 4 | 6 | [3, 4, 5, 6] | | 1 | 7 | 7 | [5, 6, 7] | | 1 | 11 | 8 | [6, 7, 8] | | 2 | NULL | 9 | [9, 10] | | 2 | NULL | 10 | [9, 10] | +------------+------------+------------+--------+
彙總函式
MaxCompute SQL支援的彙總函式如下。
函數 | 功能 |
計算平均值。 | |
計算記錄數。 | |
計算指定運算式為True的記錄數。 | |
計算最大值。 | |
計算最小值。 | |
計算中位元。 | |
計算總體標準差。 | |
計算樣本標準差。 | |
計算匯總值。 | |
用指定的分隔字元連接字串。 | |
在指定範圍內任選一個值返回。 | |
返回輸入的非重複值的近似數目。 | |
返回指定列的最大值對應行的列值。 | |
返回指定列的最小值對應行的列值。 | |
返回指定列的最大值對應行的列值。 | |
返回指定列的最小值對應行的列值。 | |
將指定的列彙總為一個數組。 | |
將指定的列彙總為一個無重複元素的數組。 | |
統計指定列的近似長條圖。 | |
計算近似百分位元,適用於巨量資料量。 | |
計算輸入Value的bit OR彙總值。 | |
計算輸入Value的bit AND彙總值。 | |
構造兩個輸入欄位的Map。 | |
構造兩個輸入欄位的Map,第一個欄位作為Map的Key,第二個欄位構造數組作為Map的Value。 | |
對輸入Map進行Union操作來構造輸出Map。 | |
對輸入Map進行Union操作並對相同Key的Value求和來構造輸出Map。 | |
構造輸入Map的Key值出現次數的Map。 |
彙總函式文法
彙總函式的文法聲明如下。
<aggregate_name>(<expression>[,...]) [within group (order by <col1>[,<col2>…])] [filter (where <where_condition>)]
<aggregate_name>(<expression>[,...])
:內建彙總函式或使用者自訂彙總函式UDAF,具體格式以實際彙總函式文法為準。within group (order by <col1>[,<col2>…])
:當彙總函式中攜帶該運算式時,預設會對<col1>[,<col2>…]
的輸入資料進行升序排列。如果需要降序排列,運算式為within group (order by <col1>[,<col2>…] [desc])
。在使用該運算式時,您需要注意:
僅支援WM_CONCAT、COLLECT_LIST、COLLECT_SET及UDAF使用該運算式。
一個SELECT語句中如果多個彙總函式攜帶
within group (order by <col1>[,<col2>…])
運算式時,order by <col1>[,<col2>…]
必須相同。如果彙總函式的參數中攜帶了DISTINCT關鍵字,
order by <col1>[,<col2>…]
中必須包含DISTINCT的列。
命令樣本如下:
--樣本一,對輸入資料升序排列後輸出。 select x, wm_concat(',', y) within group (order by y) from values('k', 1),('k', 3),('k', 2) as t(x, y) group by x; --返回結果如下。 +------------+------------+ | x | _c1 | +------------+------------+ | k | 1,2,3 | +------------+------------+ --樣本二,對輸入資料降序排列後輸出。 select x, wm_concat(',', y) within group (order by y desc) from values('k', 1),('k', 3),('k', 2) as t(x, y) group by x; --返回結果如下。 +------------+------------+ | x | _c1 | +------------+------------+ | k | 3,2,1 | +------------+------------+
[filter (where <where_condition>)]
:當彙總函式中攜帶該運算式時,彙總函式只會處理滿足<where_condition>
的資料。更多<where_condition>
資訊,請參見WHERE子句(where_condition)。在使用該運算式時,您需要注意:
命令樣本如下:
--樣本一,過濾並彙總資料。 select sum(x), sum(x) filter (where y > 1), sum(x) filter (where y > 2) from values(null, 1),(1, 2),(2, 3),(3, null) as t(x, y); --返回結果如下。 +------------+------------+------------+ | _c0 | _c1 | _c2 | +------------+------------+------------+ | 6 | 3 | 2 | +------------+------------+------------+ --樣本二,使用多個彙總函式過濾並彙總資料。 select count_if(x > 2), sum(x) filter (where y > 1), sum(x) filter (where y > 2) from values(null, 1),(1, 2),(2, 3),(3, null) as t(x, y); --返回結果如下。 +------------+------------+------------+ | _c0 | _c1 | _c2 | +------------+------------+------------+ | 1 | 3 | 2 | +------------+------------+------------+
過濾條件運算式
使用限制。
僅MaxCompute內建的彙總函式支援添加過濾條件運算式,自訂彙總函式UDAF暫不支援。
count(*)
不能與過濾條件運算式同時使用,請使用COUNT_IF函數。
命令格式。
<aggregate_name>(<expression>[,...]) [filter (where <where_condition>)]
命令說明。
彙總函式都可以增加過濾條件運算式。如果指定了過濾條件,則只有滿足過濾條件的行資料才會傳給對應的彙總函式進行處理。
參數說明。
aggregate_name:必填。彙總函式名稱,請根據實際需求選擇下方的彙總函式。
expression:必填。彙總函式的參數。請根據各個彙總函式的參數說明填寫。
where_condition:可選。過濾條件。更多過濾條件資訊,請參見WHERE子句(where_condition)。
傳回值說明。
請參見各個彙總函式的傳回值說明。
使用樣本。
select sum(sal) filter (where deptno=10), sum(sal) filter (where deptno=20), sum(sal) filter (where deptno=30) from emp;
返回結果如下:
+------------+------------+------------+ | _c0 | _c1 | _c2 | +------------+------------+------------+ | 17500 | 10875 | 9400 | +------------+------------+------------+
字串函數
MaxCompute SQL支援的字串函數如下。其中字串函數的使用限制請參見字串函數的使用限制。
函數 | 功能 |
返回字串的第一個字元的ASCII碼。 | |
計算A字串出現在B字串中的字元個數。 | |
將指定ASCII碼轉換成字元。 | |
將字串串連在一起。 | |
將參數中的所有字串按照指定的分隔字元串連在一起。 | |
將字串按照指定編碼格式解碼。 | |
將字串按照指定編碼格式編碼。 | |
在以逗號分隔的字串中尋找指定字串的位置。 | |
將數字轉化為指定格式的字串。 | |
根據給定的JSON字串和輸出格式資訊,返回ARRAY、MAP或STRUCT類型。 | |
在一個標準JSON字串中,按照指定方式抽取指定的字串。 | |
將字串轉換為固定格式的字串,單詞之間以空格分隔。轉換後的格式為:字串中每個單字首大寫,其餘小寫。 | |
計算A字串在B字串中的位置。 | |
判斷字串是否可以從指定的A字元集轉換為B字元集。 | |
將字串拆分為Key-Value對,並將Key-Value對分開,返回Key對應的Value。 | |
將字串拆分為多個Key-Value對,並將Key-Value對分開,返回多個Key對應的Value。 | |
計算字串的長度。 | |
計算字串以位元組為單位的長度。 | |
在字串中尋找另一指定字串的位置。 | |
去除字串的左端字元。 | |
計算字串的MD5值。 | |
對URL進行解析返回指定部分的資訊。 | |
對URL進行解析返回多個部分的資訊。 | |
計算字串從指定位置開始,匹配指定規則的子串數。 | |
將字串按照指定規則拆分為組後,返回指定組的字串。 | |
返回字串從指定位置開始,與指定規則匹配指定次數的子串的起始或結束位置。 | |
將字串中,與指定規則在指定次數匹配的子串替換為另一字串。 | |
返回字串中,從指定位置開始,與指定規則匹配指定次數的子串。 | |
返回將字串重複指定次數後的結果。 | |
返回倒序字串。 | |
去除字串的右端字元。 | |
產生空白字元串。 | |
按照分隔字元拆分字串,返回指定部分的子串。 | |
返回STRING類型字串從指定位置開始,指定長度的子串。 | |
返回STRING或BINARY類型字串從指定位置開始,指定長度的子串。 | |
將BOOLEAN、BIGINT、DECIMAL或DOUBLE類型值轉為對應的STRING類型表示。 | |
將指定的複雜類型輸出為JSON字串。 | |
將字串中的英文字元轉換為小寫形式。 | |
將字串中的英文字元轉換為大寫形式。 | |
去除字串的左右兩端字元。 | |
將字串從 | |
將字串編碼為 | |
在一個標準的JSON字串中,按照輸入的一組鍵抽取各個鍵指定的字串。 | |
將字串向左補足到指定位元。 | |
將字串向右補足到指定位元。 | |
將字串中與指定字串匹配的子串替換為另一字串。 | |
將一般字元串替換為SOUNDEX字串。 | |
截取字串指定分隔字元前的字串。 | |
將A出現在B中的字串替換為C字串。 | |
在字串中尋找所有出現的Regex匹配的子字串,並把找到的字串以數組形式返回。 |
複雜類型函數
MaxCompute SQL支援的複雜類型函數如下。其中JSON函數的使用限制請參見JSON函數的使用限制。
函數類別 | 函數 | 功能 |
ARRAY函數 | 判斷ARRAY數組中是否所有元素都滿足指定條件。 | |
判斷ARRAY數組中是否存在滿足指定條件的元素。 | ||
使用給定的值構造ARRAY。 | ||
檢測指定的ARRAY中是否包含指定的值。 | ||
去除ARRAY數組中的重複元素。 | ||
找出在ARRAY A中,但不在ARRAY B中的元素,並去掉重複的元素後,以ARRAY形式返回結果。 | ||
計算兩個ARRAY數組的交集。 | ||
將ARRAY數組中的元素按照指定字串進行拼接。 | ||
計算ARRAY數組中的最大值。 | ||
計算ARRAY數組中的最小值。 | ||
計算指定元素在ARRAY數組中第一次出現的位置。 | ||
將ARRAY數組的元素進行彙總。 | ||
在ARRAY數組中刪除指定元素。 | ||
返回將指定元素重複指定次數後的ARRAY數組。 | ||
將ARRAY數組的元素進行排序。 | ||
計算兩個ARRAY數組的並集並去掉重複元素。 | ||
判斷兩個ARRAY數組中是否包含相同元素。 | ||
合并多個ARRAY數組。 | ||
將ARRAY數組或字串串連在一起。 | ||
將一行資料轉為多行的UDTF。 | ||
將ARRAY數組中的元素進行過濾。 | ||
返回ARRAY數組指定位置的元素值。 | ||
將指定的ARRAY展開,每個Value一行,每行兩列分別對應數組從0開始的下標和數組元素。 | ||
返回指定ARRAY中的元素數目。 | ||
對ARRAY資料切片,返回從指定位置開始、指定長度的數組。 | ||
為指定的數組中的元素排序。 | ||
將ARRAY數組中的元素進行轉換。 | ||
將2個ARRAY數組按照位置進行元素層級的合并。 | ||
MAP函數 | 將一行資料轉為多行的UDTF。 | |
返回MAP型別參數中滿足指定條件的Value。 | ||
使用指定的Key-Value對建立MAP。 | ||
返回多個MAP的並集。 | ||
將MAP中的Key、Value索引值映射轉換為STRUCT結構數組。 | ||
將MAP中的元素進行過濾。 | ||
通過給定的ARRAY數組構造MAP。 | ||
通過給定的結構體數組構造MAP。 | ||
將參數MAP中的所有Key作為數組返回。 | ||
將參數MAP中的所有Value作為數組返回。 | ||
對輸入的兩個MAP進行合并得到一個新MAP。 | ||
返回指定MAP中的K/V對數。 | ||
對MAP進行變換,保持Value不變,根據指定Function Compute新的Key。 | ||
對MAP進行變換,保持Key不變,根據指定Function Compute新的Value。 | ||
STRUCT函數 | 擷取STRUCT中的成員變數的取值。 | |
將指定的STRUCT數組展開。每個數組元素對應一行,每行每個STRUCT元素對應一列。 | ||
使用給定Value列表建立STRUCT。 | ||
使用給定的Name、Value列表建立STRUCT。 | ||
JSON函數 | 根據給定的JSON字串和輸出格式資訊,返回ARRAY、MAP或STRUCT類型。 | |
在一個標準JSON字串中,按照指定方式抽取指定的字串。 | ||
在一個標準的JSON字串中,按照輸入的一組鍵抽取各個鍵指定的字串。 | ||
將指定的複雜類型輸出為JSON字串。 | ||
產生JSON OBJECT,要求key和value成對出現。 | ||
產生JSON ARRAY。將一個可能為空白的JSON類型對象,轉換為包含這些類型的數組。 | ||
解析JSON運算式中對應json_path的資料,注意json_path非法時會報錯。 | ||
查看json_path對應的JSON值是否存在。 | ||
美化JSON,增加換行及空格。 | ||
返回JSON資料所屬的資料類型名稱。 | ||
將JSON資料轉換成STRING類型,預設不自動進行美化。 | ||
將STRING類型轉成JSON類型,非JSON格式轉換為字串會報錯。 | ||
檢查字串是否為合法的JSON格式。 | ||
支援基本類型與JSON類型的轉換。 |
加密函數
MaxCompute SQL支援的加密函數如下。
函數 | 功能 |
對錶裡的指定列做隨機性加密,返回BINARY類型的密文。 | |
對錶裡的指定已經隨機性加密的列做解密,BINARY類型的明文。 |
其他函數
MaxCompute SQL支援的其他類型函數如下。
函數 | 功能 |
將二進位表示值轉換為BASE64編碼格式字串。 | |
篩選滿足區間條件的資料。 | |
根據運算式的計算結果,靈活地返回不同的值。 | |
將運算式的結果轉換為目標資料類型。 | |
返回參數列表中第一個非NULL的值。 | |
對STRING或BINARY類型輸入參數按照GZIP演算法進行壓縮。 | |
計算字串或位元據的迴圈冗餘校正值。 | |
實現 | |
對BINARY類型輸入參數按照GZIP演算法進行解壓。 | |
根據社會安全號碼碼返回當前的年齡。 | |
根據社會安全號碼碼返回出生日期。 | |
根據社會安全號碼碼返回性別。 | |
擷取當前帳號的帳號ID。 | |
返回輸入參數中最大的值。 | |
根據輸入參數計算Hash值。 | |
判斷指定的條件是否為真。 | |
返回輸入參數中最小的值。 | |
返回分區表的一級分區的最大值。 | |
比較兩個入參是否相等。 | |
指定值為NULL的參數的返回結果。 | |
將輸入變數按從小到大排序後,返回指定位置的值。 | |
查詢指定的分區是否存在。 | |
對所有讀入的列值,採樣並過濾掉不滿足採樣條件的行。 | |
計算字串或位元據的SHA-1雜湊值。 | |
計算字串或位元據的SHA-1雜湊值。 | |
計算字串或位元據的SHA-2雜湊值。 | |
判斷正負值屬性。 | |
將字串按照指定的分隔字元分割後返回數組。 | |
將指定的參數組分割為指定的行數。 | |
將字串按照指定的分隔字元分割得到Key和Value。 | |
查詢指定的表是否存在。 | |
將一行資料轉為多行的UDTF,將列中儲存的以固定分隔字元格式分隔的數組轉為多行。 | |
將一行資料轉為多行資料的UDTF,將不同的列拆分為不同的行。 | |
將BASE64編碼格式字串轉換為二進位表示值。 | |
返回一個隨機ID,運行效率高於UUID函數。 | |
返回一個隨機ID。 |
JSON函數的使用限制
目前支援的開發套件括odpscmd用戶端,Studio和DataWorks,暫不支援Dataphin等外圍生態。如果需要跟外部系統做組合使用時,請先確認後再使用。使用odpscmd用戶端和Studio時需要關注以下內容。
使用odpscmd用戶端
使用Studio
需要將用戶端升級到最新版本,否則無法使用
desc json_table
命令。需要將用戶端安裝路徑下的conf\odps_config.ini檔案中的參數
use_instance_tunnel
設定為false,否則查詢會報錯。
Studio只支援查詢JSON類型的操作,不支援上傳、下載JSON類型資料。
如果表存在其他引擎讀取情況,比如Hologres等,目前不支援讀取JSON資料類型。
暫不支援對一張表新增JSON列。
暫不支援對JSON類型的比較操作,也不支援對JSON類型進行
ORDER BY
、GROUP BY
或作為JOIN
的key等。目前JSON NUMBER的整數和小數分別使用BIGINT和DOUBLE類型進行儲存。當整數部分超出BIGINT範圍時會溢出,小數轉為DOUBLE時會損失精度。
產生JSON類型資料所用的字串裡不支援UNICODE
\u0000
。Java UDF和Python UDF暫不支援JSON類型。
目前JSON類型不支援Cluster表。
字串函數的使用限制
以下函數只支援英文字元的轉換:
TRIM/RTRIM/LTRIM:trimChars只支援英文字元。
REVERSE:在Hive模式下只支援英文字元。
SOUNDEX:僅轉換英文字元。
TOLOWER:將字串中的英文字元轉換為小寫形式。
TOUPPER:將字串中的英文字元轉換為大寫形式。
INITCAP:將字串中每個單詞首字母(英文字元)轉化為大寫形式,其餘為小寫。