SQL拆分字段内容(含分隔符)

07-06 1050阅读

问题描述:

在做数据迁移的过程中,我们希望对表中的某个字段根据分隔符进行拆分,得到多条数据,原代码有点意思,因此记录一下。

我们假设某条数据如下:

IDSTR
S1公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效

针对这条数据,我们希望将其拆分成为四份或者五份,以便于后续的数据处理(这里是拆成四份,加上原来的那条数据一共是五条)。

希望得到的结果:

STEP1:

IDSTR
S1公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效
S1公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效
S1公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效
S1公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效
S1公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效

原作者最后希望得到如下的数据:

STEP2:

IDSTR
S1公司名称不能小于四个字,
S1行业类别不能为空,
S1职务/岗位不能为空,
S1公司电话不能小于8位且真是有效

DB2原代码

针对STEP1:

原来的代码:

WITH N (STR,ORI,POS,ID) AS 
(
(SELECT CONCAT(STR,','),
       1,
       POSSER(CONCAT(STR,','),','),
       ID
  FROM TABLE_NAME
  WHERE ID = 'S1')
  UNION ALL
  SELECT 
  STR,
  POS+1,
  LOCATE(',',STR,POS+1),
  STR
  FROM N 
  WHERE LOCATE(',',STR,POS+1)+1>0)
  SELECT * FROM N 

结果如下:

STRORIPOSID
公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效122S1
公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效2339S1
公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效4057S1
公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效5889S1
公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效9090S1

关于代码中涉及到的函数说明

CONCAT()

拼接函数

组合两部分形成一个字符串表达。

(看官方文档,只包括两个参数)

CONCAT官方说明

SQL拆分字段内容(含分隔符)

POSSER()

函数返回查找字符串在被查找字符串中第一次出现的位置。

SQL拆分字段内容(含分隔符)

POSSTR官方文档

官网示例:

Example: Select the RECEIVED column, the SUBJECT column, and the starting position of the string ‘GOOD BEER’ within the NOTE_TEXT column for all rows in the IN_TRAY table that contain that string.

结果返回RECEIVED列, SUBJECT列,以及字符串 ‘GOOD BEER’ 在 NOTE_TEXT列中第一次出现的位置。

   SELECT RECEIVED, SUBJECT, POSSTR(NOTE_TEXT, 'GOOD BEER')
     FROM IN_TRAY
     WHERE POSSTR(NOTE_TEXT, 'GOOD BEER')  0;

LOCATE()

SQL拆分字段内容(含分隔符)

LOCATE()函数与POSSER()类似,参数数量不同

LOCATE()函数返回查找字符串在被查找字符串中第一次出现的位置,与POSSER()不同的是,它可以指定开始的位置以及编码计算的方式(CODEUNITS16, CODEUNITS32, or OCTETS)。

官方示例:

Locate the character ‘ß’ in the string ‘Jürgen lives on Hegelstraße’, and set the host variable LOCATION with the position, as measured in CODEUNITS32 units, within the string.

返回字符 'ß’在字符串’Jürgen lives on Hegelstraße’中的位置,从第一位之后开始计算

   SET :LOCATION = LOCATE('ß','Jürgen lives on Hegelstraße',1,CODEUNITS32);

GBASE实现

上例改写

参考文章:

MySql字符串拆分实现split功能(字段分割转列、转行)

GBASE中 WITH AS 函数相较于DB2会有限制,因此不推荐使用(需要指定模式名称)

对于这个问题,我们要明确:

1、循环多少次

2、如何控制循环的次数

循环次数求取:

对于该字符串:

公司名称不能小于四个字,行业类别不能为空,职务/岗位不能为空,公司电话不能小于8位且真是有效

我们需要将其分为四段,每个逗号作为分隔

那么循环次数可以这样表示:

LENGTH(STR) - LENGTH(REPLACE(STR,',',''))

将逗号替换为空格,用含逗号的字符串的长度减去不含逗号的字符串长度,得到的就是逗号的数量,也就是循环的次数

对于如何控制循环,我们需要引入一个序列数,上述文章使用了MySQL中的系统表中的ID作为序列,我们可以新建一个表,存入这个自增序列作为辅助,因为希望在一个sql中完成这个操作,因此我这里使用row_number()over()函数自己创建一个序列

那么完整地代码如下所示:

SELECT H1.ID ,
      SUBSTRING_INDEX(SUBSTRING_INDEX(H1.STR,',',SEQ),',',-1)  AS STR
 FROM TABLENAME
 INNER JOIN (SELECT ROW_NUMBER()OVER(ORDER BY STR) AS SEQ ,T.* 
               FROM TABLENAME T 
               ORDER BY SQE) H2
          ON H2.SEQ
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]