前言
经常用不会忘记的,我这就不再赘述了
字符串相关
常用函数汇总
函数名 |
函数功能 |
函数定义 |
CHAR_MATCHCOUNT |
返回str1中有多少个字符出现在str2中 |
bigint char_matchcount(string str1, string str2) |
将给定ASCII码ascii转换成字符 |
string chr(bigint ascii) |
|
CONCAT |
连接字符串 |
string concat(string a, string b...) |
KEYVALUE |
返回key-value对中key所对应的value |
KEYVALUE(STRING srcStr,STRING split1,STRING split2, STRING key) KEYVALUE(STRING srcStr, STRING key) //split1 = ";",split2 = ":" |
REGEXP_REPLACE |
字符串替换 |
string regexp_replace(string source, string pattern, string replace_string[, bigint occurrence]) |
SPLIT_PART |
根据分隔符拆分字符串 |
string split_part(string str, string separator, bigint start[, bigint end])) |
SUBSTR |
返回字符串指定位置指定长度的的子串。字符串替换 |
string substr(string str, bigint start_position[, bigint length]) |
CHAR_MATCHCOUNT: 计算str1中有多少个字符出现在str2中
函数声明:
bigint char_matchcount(string str1, string str2)
用途:用于计算str1中有多少个字符出现在str2中。
参数说明:
- str1,str2:String类型,必须为有效的UTF-8字符串,如果对比中发现有无效字符则函数返回负值。
返回值:Bigint类型。任一输入为NULL返回NULL。
示例:
char_matchcount('abd','aabc') = 2 -- str1中得两个字符串'a', 'b'在str2中出现过
FIND_IN_SET:查找字符串str1在以逗号(,)分隔的字符串str2中的位置(是否存在)
函数声明:
bigint find_in_set(string <str1>, string <str2>)
用途: 查找字符串str1在以逗号(,)分隔的字符串str2中的位置,从1开始计数
参数说明:
- str1:必填。STRING类型。待查找的字符串。
- str2:必填。STRING类型。以逗号(,)分隔的字符串。
返回值说明: 返回BIGINT类型。返回规则如下:
- 当str2中无法匹配到str1或str1中包含逗号(,)时,返回0。
- 当str1或str2为NULL时,返回结果为NULL
示例1:查找字符串ab在字符串abc,hello,ab,c中的位置。命令示例如下。
select find_in_set('ab', 'abc,hello,ab,c'); --返回3
备注:判断是否存在时场景,只需要设置返回值>0即可
行列转化
列转行
方式一:自身join
在ODPS中,可以通过自身的JOIN操作来实现列转行的操作。具体步骤如下:
假设有一个表t1,包含三列id、name、value,如下所示:
id |
name |
value |
1 |
A |
value1 |
1 |
A |
value2 |
1 |
A |
value3 |
2 |
B |
value2 |
2 |
B |
value3 |
3 |
C |
value1 |
3 |
C |
value2 |
3 |
C |
value3 |
现在需要将value列中的值转为一行,可以使用自身的JOIN操作来实现,如下所示:
SELECT t1.id, t1.name, t2.value FROM t1 JOIN t1 t2 ON t1.id = t2.id WHERE t1.value = 'value1' AND t2.value = 'value2';
执行以上SQL语句后,可以得到以下结果:
id |
name |
value |
1 |
A |
value2 |
3 |
C |
value2 |
在结果表中,只保留了满足条件的数据,即t1表中value列为'value1'且t2表中value列为'value2'的行。通过自身JOIN操作,将满足条件的数据连接到一起。
需要注意的是,自身JOIN操作会产生笛卡尔积,因此在实际使用时需要根据实际情况添加适当的筛选条件(例如WHERE子句),以保证结果的准确性。
方式二: COLLECT_LIST + CONCAT_WS
COLLECT_LIST:
将colname指定的列值聚合为一个数组 (此函数为MaxCompute 2.0扩展函数)
- 命令格式
array collect_list(<colname>)
- 返回值说明
返回ARRAY类型。colname值为NULL时,该行不参与计算。
CONCAT_WS
返回将参数中的所有字符串或ARRAY数组中的元素按照指定的分隔符连接在一起的结果。此函数为MaxCompute 2.0扩展函数。
- 命令格式
string concat_ws(string <separator>, string <str1>, string <str2>[,...]) string concat_ws(string <separator>, array<string> <a>)
用COLLECT_LIST和CONCAT_WS函数实现行转列的示例:
SELECT id, CONCAT_WS(',', COLLECT_LIST(value)) AS merged_col FROM t GROUP BY id;
在这个示例中,我们使用COLLECT_LIST函数将每个id对应的value列的值收集为一个数组。然后,我们使用CONCAT_WS函数将数组中的值连接成一个字符串,使用逗号作为分隔符。
执行上述查询后,将得到以上所示的结果。
可以看到,我们成功地将每个id对应的所有值合并为一个列,并按id进行了分组。
需要注意的是,行转列的结果将依赖于原始数据的分组情况。在上述示例中,我们按id进行了分组,因此每个id对应的值被合并为一个单独的字符串。
如果想要将多个列转换为一列,只需在CONCAT_WS函数中添加需要合并的列即可。
方式三: WM_CONCAT
用指定的separator做分隔符,连接colname中的值。
命令格式
string wm_concat(string <separator>, string <colname>)
参数说明
- separator:必填。STRING类型常量,分隔符。
- colname:必填。STRING类型。如果输入为BIGINT、DOUBLE或DATETIME类型,会隐式转换为STRING类型后参与运算。
- 示例 下面是如何使用WM_CONCAT函数的示例:
假设有一个表student_scores,结构如下:
| student_id | subject | score | |------------|---------|-------| | 1 | Math | 90 | | 1 | English | 85 | | 2 | Math | 75 | | 2 | English | 80 |
我们想要将每个学生的所有科目和分数合并为一个字符串,可以使用以下SQL查询:
1SELECT 2 student_id, 3 WM_CONCAT(',', subject) AS subjects, 4 WM_CONCAT(',', CAST(score AS STRING)) AS scores 5FROM 6 student_scores 7GROUP BY 8 student_id;
执行上述查询后,你将得到每个student_id对应的所有subject和score,合并成一个以逗号分隔的字符串。示例如下:
| student_id | subjects | scores | |------------|----------------|--------| | 1 | Math,English | 90,85 | | 2 | Math,English | 75,80 |
请注意,WM_CONCAT函数的参数是要连接的字段,以及用作分隔符的字符串(在这个例子中是逗号)。由于WM_CONCAT只接受字符串类型,因此需要将数值类型的score转换为字符串类型,这里使用了CAST函数。
这种方法有个潜在的问题:默认情况下,WM_CONCAT函数不保证元素的顺序。如果顺序对你的应用很重要,你可能需要考虑其他方法来确保顺序,比如使用ROW_NUMBER()函数先对数据进行排序。
备注:wm_concat无法作用于数组
行转列
Lateral View
DPS中的Lateral View语句用于将一个表的列(含分隔符)展开成多行,通常用于处理数组或集合类型的列
SELECT ... FROM table LATERAL VIEW [OUTER] udtf(expression) AS alias_column
假设已有一张表pageAds,它有三列数据,第一列是pageid string,第二列是col1 array<int>,第三列是col2 array<string>,详细数据如下。
pageid |
col1 |
col2 |
front_page |
[1, 2, 3] |
[“a”, “b”, “c”] |
contact_page |
[3, 4, 5] |
[“d”, “e”, “f”] |
单个 Lateral View语句拆分col1。命令示例如下:
select pageid, col1_new, col2 from pageAds lateral view explode(col1) adTable as col1_new; -- 返回结果如下: +--------------+------------+-------------+ | pageid | col1_new | col2 | +--------------+------------+-------------+ | front_page | 1 | ["a","b","c"] | | front_page | 2 | ["a","b","c"] | | front_page | 3 | ["a","b","c"] | | contact_page | 3 | ["d","e","f"] | | contact_page | 4 | ["d","e","f"] | | contact_page | 5 | ["d","e","f"] | +------------+------------+------------+
集合操作:交集、并集和补集
- 交集:求两个数据集的交集,即输出两个数据集均包含的记录。
- 并集:求两个数据集的并集,即将两个数据集合并成一个数据集。
- 补集:求第二个数据集在第一个数据集中的补集,即输出第一个数据集包含而第二个数据集不包含的记录。
交集 ( intersect all/intersect [distinct] )
方式一:INNER JOIN 。。。基操忽略
方式二:
- 命令格式
--取交集不去重。 <select_statement1> intersect all <select_statement2>; --取交集并去重。intersect效果等同于intersect distinct。 <select_statement1> intersect [distinct] <select_statement2>;
- 参数说明
- select_statement1、select_statement2:必填。select语句,格式请参见SELECT语法。
- distinct:可选。对两个数据集取交集的结果去重。
并集 ( union all/union [distinct] )
- 命令格式
--取并集不去重。 <select_statement1> union all <select_statement2>; --取并集并去重。 <select_statement1> union [distinct] <select_statement2>;
- 注意事项
- 存在多个union all时,支持通过括号指定union all的优先级。
- union后如果有cluster by、distribute by、sort by、order by或limit子句时,如果设置set odps.sql.type.system.odps2=false;,其作用于union的最后一个select_statement;如果设置set odps.sql.type.system.odps2=true;时,作用于前面所有union的结果。
- 参数说明
- select_statement1、select_statement2:必填。select语句
- distinct:可选。对两个数据集取并集的结果去重。
补集( except all/minus all/except [distinct]/minus [distinct] )
- 命令格式
--取补集不去重。 <select_statement1> except all <select_statement2>; <select_statement1> minus all <select_statement2>; --取补集并去重。 <select_statement1> except [distinct] <select_statement2>; <select_statement1> minus [distinct] <select_statement2>;
说明 except和minus等效。
- 参数说明
- select_statement1、select_statement2:必填。select语句
- distinct:可选。对取补集的结果去重。
TopN(ROW_NUMBER() OVER)
按照某一个字段分组后取某个分组的前N行
诉求:假设您有一个名为table_name的ODPS表,其中有一个字段为group_field,您可以按照group_field字段进行分组,并取每个分组的前200条数据
方式1: 可以使用ODPS的分区操作来按照某个字段进行分组,并使用LIMIT子句来限制每个分组的数据条数。
方式2: 使用ROW_NUMBER窗口函数
SELECT * FROM ( SELECT *, ROW_NUMBER() OVER(PARTITION BY group_field ORDER BY your_order_field) AS rn FROM table_name ) t WHERE rn <= 200
先利用ROW_NUMBER()函数为每个分组内的数据进行编号,然后再筛选出行号小于等于200的数据。
注意:请注意,这个方法适用于每个分组的数据量不大的情况,如果每个分组的数据量很大,可能会影响查询的性能。如果有大量数据需要处理,您可能需要考虑使用其他更高效的方法。
完整的文档,建议直接看官方文档:
https://help.aliyun-inc.com/internaldoc/detail/413657.html?spm=a2c1f.8259796.2.112.QbF0CL