暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

DEV01-GBase 8a MPP Cluster SQL 编码进阶篇之内置函数07

wiserhowe 2024-01-10
558
(十)正则函数

    使用正则表达式的内置函数叫做正则函数。在讲解正则函数之前需要熟悉正则表达式。

0、正则表达式

  • 正则的功能
    (1) 校验数据有效性
    (2) 查找符合要求的文本内容
    (3) 对文本进行切割,替换等操作
  • 元字符的概念
    (1) 正则表达式是由一系列元字符组成的匹配字串;
    (2) 元字符是正则表达式中具有特殊意义的专用字符;
    (3) 构成正则表达式的基本元件。
  • 元字符的构成
    在这里插入图片描述

(1) 特殊单字符

字符 描述
. 匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\w 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。
\W 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’。 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 后向引用、或一个八进制转义符。例如,‘n’ 匹配字符 “n”。’\n’ 匹配一个换行符。序列 ‘\’ 匹配 “”
^ 匹配输入字符串的开始位置。
$ 匹配输入字符串的结束位置。

(2) 空白符

字符 描述
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
\B 匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。

(3) 量词

字符 描述
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。 * 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,‘zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,“do(es)?” 可以匹配 “do” 或 “does” 中的"do" 。? 等价于 {0,1}。
{n} n 是自然数。匹配确定的 n 次。例如,‘o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。
{n,} n 是自然数。至少匹配n 次。例如,‘o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。‘o{1,}’ 等价于 ‘o+’。‘o{0,}’ 则等价于 ‘o*’。
{n,m} m 和 n 均为自然数,n <= m。最少匹配 n 次且最多匹配 m 次。刘, “o{1,3}” 将匹配 “fooooood” 中的前三个 o。‘o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。

(4) 范围

字符 描述
| 表示“或”的关系。比如 (http?|ftp):\/\/
[a-z] 表示匹配 26 个小写字母之一
[^a-z] 取反,匹配 26 个小写字母之外的某个字符

1、REGEXP_LIKE (source_char, pattern [, match_paramater])
功能:正则匹配,使用正则表达式匹配源字符串。

参数 说明
source_char 源字符串。该参数支持的数据类型与replace函数的src参数一致。
pattern 正则表达式。仅支持字符串,最多可包含512个字节
match_paramater i:大小写不敏感;
c:大小写敏感;
n:点号(.)匹配换行符号;
m:多行模式;
x:扩展模式,忽略正则表达式中的空白字符
  • REGEXP_LIKE 练习
    测试表 test_reg 的数据
id value
1 1234560
2 I can swim
3 1b3b560
4 abc
5 abcde
6 ADREasx
7 123 45
8 adc de
9 adc,.de
10 1B
10 abcbvbnb
11 11114560
11 11124560

(1) 查询value中以1开头60结束的记录并且长度是7位

select * from test_reg where value like '1____60'; # 使用 like,结果是正确的。每个“_”表示一个字符。 select * from test_reg where regexp_like(value,'1.{4}60'); # 贪婪模式造成多匹配出两个记录。贪婪模式是最大长度匹配,只要1到60之间找到4个字符,即为匹配。 select * from test_reg where regexp_like(value,'^1.{4}60$'); # 这是符合需求的最精确的正则。非贪婪模式,1到60之间存在且只有4个字符,才能匹配。“^”表示匹配开始,“$”表示匹配结束。
复制

(2) 查询value中以1开头60结束的记录并且长度是7位并且全部是数字的记录;

select * from test_reg where regexp_like(value,'^1[0-9]{4}60$'); select * from test_reg where regexp_like(value,'^1[\\d]{4}60$'); # \d 匹配一个数字字符 select * from test_reg where regexp_like(value,'^1[[:digit:]]{4}60$');-- 也可以使用字符集
复制

(3) 查询value中不是纯数字的记录

select * from test_reg where not regexp_like(value,'^[[:digit:]]+$'); # “[[:digit:]]” 是 PHP 正则表达式的通用字符簇,表示任何数字
复制

(4) 查询value中不包含任何数字的记录

select * from test_reg where regexp_like(value,'^[^[:digit:]]+$'); # “[[:digit:]]” 是 PHP 正则表达式的通用字符簇,表示任何数字。该表达式匹配到不存在数字的源字串
复制

(5) 查询以12或者1b开头的记录.不区分大小写

select * from test_reg where regexp_like(value,'^1[2b]','i'); # 不区分大小写 /* id value 1 1234560 3 1b3b560 7 123 45 10 1B */
复制

(6) 查询以12或者1b开头的记录.区分大小写

select * from test_reg where regexp_like(value,'^1[2B]'); /* id value 1 1234560 7 123 45 10 1B */
复制

(7) 查询数据中包含空白的记录

select * from test_reg where regexp_like(value,'[[:space:]]'); # “[[:space:]]” 是 PHP 正则表达式的通用字符簇,表示任意空白字符(空格、制表符、回车、换行)
复制

(8) 查询所有包含小写字母或者数字的记录

select * from test_reg where regexp_like(value,'^([a-z]+|[0-9]+)$'); # 注意 “[a-z]+” 和 “[0-9]+” 之间 有 “|” 表示或的关系
复制

(9) 查询任何包含标点符号的记录

select * from test_reg where regexp_like(value,'[[:punct:]]'); # “[[:punct:]]” 是 PHP 正则表达式的通用字符簇,表示任何标点符号
复制

2、REGEXP_REPLACE (source_char,pattern[,replace_string[,position [,occurrence[match_option]]]])
功能:正则替换,用指定的字符串替换源字符串中与指定正则表达式相匹配的字符串。

参数 说明
source_char 源字符串。该参数支持的数据类型与replace函数的src参数一致。
pattern 正则表达式。每个正则表达式最多可包含512个字节。
replace_string 替换字符串。替换字符串可以包含反向引用的数字表达式(\n,n的取值范围是[1,9])
position 开始匹配的位置,如果不指定默认为1,即从source_char的第一个字符开始匹配。position 为一个正整数。
occurrence 正则匹配的序数。是一个非负的整数,默认值为0。0,表示替换所有匹配到的出现;正整数,替换第n次匹配到的出现;
match_paramater c:大小写敏感;n:点号(.)不匹配换行符号;m:多行模式;x:扩展模式,忽略正则表达式中的空白字符。
  • REGEXP_REPLACE 练习
# 1、替换数字为字母 Q select value, REGEXP_REPLACE (value,'[0-9]+','Q') AS Result from test_reg # 2、替换第三个单词为 READ #update test_reg set value='I can swim' where id=2 select value, REGEXP_REPLACE(value,'\\w+','READ', 1, 3) Result from test_reg where id=2
复制

3、REGEXP_INSTR (source_char,pattern[,position[,occurrence[,return_opt[,match_parameter[,subexpr]]]]])
功能:正则搜索,获得匹配字符串的位置。

参数 说明
source_char 源字符串。该参数支持的数据类型与replace函数的src参数一致。
pattern 正则表达式。仅支持字符串,每个正则表达式最多可包含512个字节。
position 开始匹配的位置。默认值为1,即从source_char的第一个字符开始匹配。
occurrence 正则匹配的序数。正整数,默认值为1,找到第N次匹配到的出现。
return_opt 返回值的类型,非负整数默认值为0。0,返回值为匹配位置的第一个字符的位置。n,返回匹配的字符串后紧跟着的第一个字符的位置。match_paramater
subexpr 对于含有子表达式的正则表达式,表示正则表达式中的第几个子串是函数目标。该参数值域范围是0~9,超过9,函数返回0。默认为0。0,返回与正则表达式匹配的字符的位置,全匹配上返回1,不匹配返回0;大于0,返回指定的子串的位置。该值大于子串个数时,返回0;源字符串中有括号时,按照正则支持的转义处理。

subexpr 参数不常用,本文不在赘述。

  • REGEXP_INSTR 练习
# 1、搜索数字第一次出现的位置 select value, REGEXP_INSTR (value,'[0-9]+') AS Result from test_reg # 2、找数字(从第一个字母开始匹配,找第1个匹配项目的紧跟着的第一个字符的位置) select value, REGEXP_INSTR (value,'[0-9]+', 1, 1, 1) AS Result from test_reg # position=1 表示从 value 字符串的第一个位置开始搜索;occurrence=1 表示找到第一次出现的位置;return_opt=1 表示匹配字符的下一个位置 # 3、找到第三个单词的位置 select value, REGEXP_INSTR(value,'\\w+', 1, 3) Result from test_reg where id=2
复制

4、REGEXP_SUBSTR (source_char,pattern[,position[,occurrence]])
功能:获得匹配到的字符串。

参数 说明
source_char 源字符串。该参数支持的数据类型与replace函数的src参数一致。
pattern 正则表达式。仅支持字符串,每个正则表达式最多可包含512个字节。
position 开始匹配的位置。默认值为1,即从source_char的第一个字符开始匹配。
occurrence 正则匹配的序数。正整数,默认值为1,找到第N次匹配到的出现。
  • REGEXP_SUBSTR 练习
# 1、搜索第一次出现的数字 select value, REGEXP_SUBSTR (value,'[0-9]+') AS Result from test_reg # 2、找到第三个单词的内容 select value, REGEXP_SUBSTR(value,'\\w+', 1, 3) Result from test_reg where id=2
复制
(十一)信息函数

1、Database():返回当前数据库名字,比如

courseware
复制

2、User():返回当前用户名,比如

root@127.0.0.1
复制

3、Version():返回当前系统版本,比如

9.5.2.39.126761
复制

4、CHARSET(<字符串>):返回字符串参数使用的字符集

函数调用 返回值
charset(‘南大通用’) utf8
(十二)函数与性能

1、函数不要用在字段上:
【优化前】select Sid, Sname, Sage from Student
where to_char(Sage,‘YYYY’) >= 2013;
【优化后】select Sid, Sname, Sage from Student
where Sage >= ‘2013-01-01’;

小贴士:函数使用在字段上,每一行字段数据都会执行函数,智能索引失效;函数使用在值上,则只执行一次,还能利用智能索引。

2、避免使用无必要的转换函数:
【优化前】select Sid, Sname, Sage from Student
where Sage >= to_date(‘2010-08-06’, ‘YYYY-MM-DD’);
【优化后】select Sid, Sname, Sage from Student
where Sage >= ‘2010-08-06’;

小贴士:WHERE 子句中,表达式的比对数值能用隐式转换就不使用数据类型转换函数。

3、超大数据量不能使用 NOT EXISTS:
【优化前】select * from Student where NOT EXISTS(select 1 from
score where SId=Student.SId)
【优化后】select * from Student where SId not in(select SId from score where SId is not null)

小贴士:需要量表关联,但是关联表字段不同值很少,表数据量较大,NOT EXISTS 会导致产生大量临时文件。改成 not in 后效率会有较大提高,但是需要加上关联字段不为空的条件。

4、巧用 COUNT( DISTINCT):
【优化前】select count(DISTINCT CId),count(DISTINCT TId) from course;
【优化后】select * from(select count(DISTINCT CId) from course)T1
join (select count(DISTINCT TId) from course)T2;

小贴士:对多列去重计数,当前执行计划先在各节点对参与 count(distinct) 的列进行分组去重,结果再汇总到一个节点进行 count(distinct) 运算。当 count(distinct) 列很多时,参与 group by 运算的列也很多,去重效果不理想,导致大量数据要拉到一个节点进行 count(distinct) 运算,拉表和汇总计算耗时非常长。优化的方法是各列分别计算 count(distinct),提高去重效果,然后对结果集进行拼接。

5、简单的模糊匹配不要使用正则匹配函数:
【优化前】select * from test_reg where REGEXP_LIKE(value, ‘^1.{4}60$’);
【优化后】select * from test_reg where value LIKE ‘1____60’

小贴士:正则匹配函数应用场景是复杂的模糊匹配,功能强大的同时,资源耗费肯定高于原生的 LIKE。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论