前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >字符转换的SQL需求增强

字符转换的SQL需求增强

作者头像
bisal
发布2019-08-15 19:46:38
5730
发布2019-08-15 19:46:38
举报

上次《字符转换的SQL需求》讨论的需求,使用各种函数,实现了字符转换的需求,但通过朋友指教,其实存在些问题。

这是原来的写法,

代码语言:javascript
复制
SQL> SELECT listagg(x.a, ';') within GROUP (ORDER BY x.a) FROM
  2  (SELECT substr(regexp_substr(a, '[^,]+',1,level),3,7)||'.'||substr(regexp_substr(a, '[^,]+',1,level),0,2) AS a
  3  FROM test
  4  connect by level <= length(decode(substr(a,-1),',',substr(a,1,length(a)-1),a)) - length(REPLACE(a,',',''))+1) x;

LISTAGG(X.A,';')WITHINGROUP(ORDERBYX.A)
--------------------------------------------------------
000001.SH;000002.SZ;000003.SZ

尚大师给出了regexp_replace和regexp_count的替代写法,

代码语言:javascript
复制
代码语言:javascript
复制
select listagg(regexp_replace(x.a, '([A-Z]{2})([0-9]{6})', '\2.\1'), ';') within group(order by x.a)from (select regexp_substr(a, '[^,]+', 1, level) afrom testconnect by level <= regexp_count(a, '[^,]+')) x;listagg(regexp_replace(x.a, '([A-Z]{2})([0-9]{6})', '\2.\1'), ';') within group(order by x.a)
from (select regexp_substr(a, '[^,]+', 1, level) a
from test
connect by level <= regexp_count(a, '[^,]+')) x;

因为当时只测了一条数据的场景,所以用这种方法,对多条数据,是会有问题的,如下所示,test存在两条数据,执行SQL,并不是我们需要的结果,无法保证汇总后的顺序,

代码语言:javascript
复制
代码语言:javascript
复制
SQL> SELECT * FROM test;A------------------------------SH000001,SZ000002,SZ000003SX000001,SX000002,SX000003SQL> SELECT listagg(x.a, ';') within GROUP (ORDER BY x.a) FROM  2  (SELECT substr(regexp_substr(a, '[^,]+',1,level),3,7)||'.'||substr(regexp_substr(a, '[^,]+',1,level),0,2) AS a  3  FROM test  4  connect by level <= length(decode(substr(a,-1),',',substr(a,1,length(a)-1),a)) - length(REPLACE(a,',',''))+1) x;LISTAGG(X.A,';')WITHINGROUP(ORDERBYX.A)--------------------------------------------------------------------------------000001.SH;000001.SX;000002.SX;000002.SX;000002.SZ;000002.SZ;000003.SX;000003.SX;000003.SX;000003.SX;000003.SZ;000003.SZ;000003.SZ;000003.SZFROM test;
A
------------------------------
SH000001,SZ000002,SZ000003
SX000001,SX000002,SX000003

SQL> SELECT listagg(x.a, ';') within GROUP (ORDER BY x.a) FROM
  2  (SELECT substr(regexp_substr(a, '[^,]+',1,level),3,7)||'.'||substr(regexp_substr(a, '[^,]+',1,level),0,2) AS a
  3  FROM test
  4  connect by level <= length(decode(substr(a,-1),',',substr(a,1,length(a)-1),a)) - length(REPLACE(a,',',''))+1) x;

LISTAGG(X.A,';')WITHINGROUP(ORDERBYX.A)
--------------------------------------------------------------------------------
000001.SH;000001.SX;000002.SX;000002.SX;000002.SZ;000002.SZ;000003.SX;000003.SX;
000003.SX;000003.SX;000003.SZ;000003.SZ;000003.SZ;000003.SZ

尚大师给出了一种解法,很酷炫,这些地儿我还得再学学,引入了rownum做层级,并用rowid进行聚类,目的应该是保证同一个rowid的转换后还是同一行,很巧妙,

代码语言:javascript
复制
代码语言:javascript
复制
SQL> select listagg(regexp_replace(xx.a, '([A-Z]{2})([0-9]{6})', '\2.\1'), ';') within group(order by xx.rn) a  2  from (select x.rowid rid, regexp_substr(a, '[^,]+', 1, y.rn) a, y.rn  3  from test x, (select rownum rn from dual connect by rownum <= 5) y  4  where y.rn <= regexp_count(x.a, '[^,]+')) xx  5  group by rid;A--------------------------------------------------------------------------------000001.SH;000002.SZ;000003.SZ000001.SX;000002.SX;000003.SX'([A-Z]{2})([0-9]{6})', '\2.\1'), ';') within group(order by xx.rn) a
  2  from (select x.rowid rid, regexp_substr(a, '[^,]+', 1, y.rn) a, y.rn
  3  from test x, (select rownum rn from dual connect by rownum <= 5) y
  4  where y.rn <= regexp_count(x.a, '[^,]+')) xx
  5  group by rid;
A
--------------------------------------------------------------------------------
000001.SH;000002.SZ;000003.SZ
000001.SX;000002.SX;000003.SX

又碰见两个新的函数,

1. REGEXP_REPLACE函数,

REGEXP_REPLACE extends the functionality of the REPLACE function by letting you search a string for a regular expression pattern. By default, the function returns source_char with every occurrence of the regular expression pattern replaced with replace_string. The string returned is in the same character set as source_char. The function returns VARCHAR2 if the first argument is not a LOB and returns CLOB if the first argument is a LOB.

2. REGEXP_COUNT函数,

REGEXP_COUNT complements the functionality of the REGEXP_INSTR function by returning the number of times a pattern occurs in a source string. The function evaluates strings using characters as defined by the input character set. It returns an integer indicating the number of occurrences of pattern. If no match is found, then the function returns 0.

另外,朱大师给出了PG的解法,

640?wx_fmt=png
640?wx_fmt=png

我只有EDB的库,虽然是PG的企业版,但这种写法,好像不支持,

640?wx_fmt=png
640?wx_fmt=png

黄老师则指出,用Oracle的SQL可以直接在达梦中跑。

谢谢各位朋友,若还有好的建议,欢迎随时留言,谢谢。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年08月09日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档