SPL 查询与报表计算实战指南 -10 字符串集合的有序计算

10 字符串集合的有序计算

这类任务是指字符串序列内或序列间的计算,常用于不规范数据的整理。SQL的基础数据类型(结果集)是无序集合,实现此类计算有天然障碍;涉及到记录级或字段级的序列时,SQL往往要转化成记录集合才能计算,代码冗长复杂,嵌入正则表达式会使代码短一些,但理解难度大,调试不便会加大这种难度。

1:在数量不定的邮件列间去除重复并合并

数据源:客户邮件表(10/MailCollected.txt)用于数据收集,由一个客户字段和数量不定的邮件字段组成,同一个客户的邮件地址可能为空、可能重复。

目标:整理成规范的二维表,去除空的邮件地址,将邮件地址去重,用逗号合并成单一的Mail字段。

Picture18png

SPL代码:


A

1

$select * from 10/MailCollected.txt

2

=A1.new(Client,~.array().m(2:).id@0().concat@c():Mail)

A1:加载数据。

A2=A1.new(Client,~.array().m(2:):Mail) 根据A1新建二维表,Client字段照抄,Mail字段分几步计算,先用函数array将记录转为序列,再用函数m取序列的第2到最后1个成员。第1条记录如图:

Picture19png
.id@0() 继续计算,用 id 函数取唯一值,@0 表示去掉空值。第 1 条记录如图:

Picture20png
.concat@c() 继续计算,用 concat 函数将序列成员合并成一个字符串,@c 表示分隔符是逗号。

2:提取NANP格式的电话号码

数据源:客户电话号码表(10/TelCollected.txt)用于数据收集,电话号码由数字和字符"()*#+-"组成,基本符合NANP格式,部分号码有国家码,部分号码是连续数字,但电话号码混在大字符串里。

目标:提取电话号码,整理成规范的二维表,规则有:1.每个telNo字段最多只有一个电话号码。2."tel"之后可能紧跟着电话号码,但没有"tel"则一定没有电话号码。3. 电话号码作为一个连续的字符串出现,遇到其他字符说明号码结束。

Picture22png

SPL代码:


A

1

$select * from 10/TelCollected.txt

2

=A1.run(TelNo=substr(TelNo,"tel").split().select@c(pos("0123456789()*#+-",~)).concat())

A1:加载数据。

A2=A1.run(TelNo=substr(TelNo,"tel")):修改TelNo字段,分为几步,先用substr函数取出标志"tel"后面的子串。

Picture23png
.split() 继续计算,用 split 函数将字符串拆分为字符序列。第 1 个字符序列如图。

Picture24png
.select@c(pos(“0123456789()*#+-”,~))继续计算,从序列的第 1 个成员开始取,直到遇到 "0123456789()*#+-" 之外的字符为止。函数 select 用于筛选,@c 表示从第 1 个成员开始取,遇到使条件为假的成员时停止。函数 pos 用于判断字符是否属于字符串。

Picture25png
.concat() 继续计算,将序列成员合并为字符串。

Picture26png

3找出至少含有 5 个连续按字母表排序的字母的字符串

数据源:某库表只有一列字符串(10/consecutive_5_str.txt),可能含有任意字符。

目标:从连续升序排列的子串中,找出最长的子串的长度大于等于 5 的字符串。 注意字母表顺序是A-Za-z,规定Z后面是a

Picture27png

SPL代码:


A

1

$select * from 10/consecutive_5_str.txt

2

=A1.select(str.split().group@i(~<=~[-1] || !isalpha(~[-1])).max(~.len())>=5)\n

A1:加载数据。

A2=A1.(str.split()) 按条件选出字符串,分为几步,先将字符串拆分成字符序列。第678个字符串如图:

Picture28png

.group@i(~<=~[-1] || !isalpha(~[-1])) 继续计算,将序列按条件分组,将按字母表排列的字符和每个非字母的字符分到不同的组。函数group用于分组但不汇总,@i表示按条件分组,~<=~[-1]表示当前字符小于上一个字符时开始新的分组,!isalpha(~[-1])表示上一个字符不是字母时开始新的分组,||表示或关系。第678个字符串如图:

Picture29png
.max(~.len())>=5 继续计算,选出组内成员数大于等于 5 的字符串。第 1-8 个字符串符合要求。

Picture30png

扩展阅读

(https://c.raqsoft.com.cn/article/1741686092621)
(https://c.raqsoft.com.cn/article/1741339210959)
(https://c.raqsoft.com.cn/article/1740479708849)
(https://c.raqsoft.com.cn/article/1734484380658)
(https://c.raqsoft.com.cn/article/1553131062284)
(https://c.raqsoft.com.cn/article/1553852557407)