SQLSERVER中WITH AS递归来实现ORACLE的INSTR函数以及固定分隔符字符串截取

分享个sqlserver的sql给大家,能用with as的递归实现oracle中的instr函数,并且能将分隔符的字符串解析,例如:

字符串为:‘O3O,30,4834,348934,AA,09WOFJOWE,FW‘

解析完成:

1)实现oracle的instr函数,sql如下:

WITH CTE1 AS (
SELECT ‘1‘ AS ID , ‘O3O,30,4834,348934,AA,09WOFJOWE,FW‘ AS STR
),
CTE2 AS (
SELECT 1 AS LEVEL,ID,STR,CHARINDEX(‘,‘,STR,1) AS POSITION
FROM CTE1
UNION ALL
SELECT LEVEL + 1 AS LEVEL,T.ID,T.STR,CHARINDEX(‘,‘,T.STR,POSITION + 1) AS POSITION
FROM CTE1 T JOIN CTE2 T1 ON T.ID = T1.ID
WHERE LEVEL < LEN(T.STR) - ISNULL(LEN(REPLACE(T.STR,‘,‘,‘‘)),0)
)
SELECT * FROM CTE2 ;

通过递归,第一次读取第一个逗号的位置,记为POSITION,然后递归,读取POSITION+1位置过后的第一个逗号的位置,递归次数由WHERE LEVEL < LEN(T.STR) - ISNULL(LEN(REPLACE(T.STR,‘,‘,‘‘)),0)去限制。

取数据的时候,只要通过ID关联,取逗号出现第几(LEVEL)次出现的位置(POSITION)即可。

2)有了如上的instr实现,那么我们就可以将字符串截取出来,下面我们来看具体实现方法。

首先,想法是这样的,既然有了POSITION,那么肯定是将第一个和第二个逗号的之间字符串截取,然后将第二个和第三个逗号之间字符串截取……第n-1个和第n个逗号之间的字符串截取。但是有个问题,‘030‘和‘FW‘,这两个字符串怎么办?其实很简单,给STR的第一个位置和最后一个位置都拼接上一个逗号即可。SQL如下:

WITH CTE1 AS (
SELECT ‘1‘ AS ID , ‘O3O,30,4834,348934,AA,09WOFJOWE,FW‘ AS STR
),
CTE2 AS (
SELECT 1 AS LEVEL,ID,STR,‘,‘ + STR + ‘,‘ AS STR_NEW,CHARINDEX(‘,‘,‘,‘ + STR + ‘,‘,1) AS POSITION
FROM CTE1
UNION ALL
SELECT LEVEL + 1 AS LEVEL,T.ID,T.STR,‘,‘ + T.STR + ‘,‘ AS STR_NEW,CHARINDEX(‘,‘,‘,‘ + T.STR + ‘,‘,POSITION + 1) AS POSITION
FROM CTE1 T JOIN CTE2 T1 ON T.ID = T1.ID
WHERE LEVEL < LEN(T.STR + ‘,‘) - ISNULL(LEN(REPLACE(T.STR + ‘,‘,‘,‘,‘‘)),0) + 1
)
SELECT * FROM CTE2 ;

实现了如上的想法,我们只要用一个LEAD函数,将后面一个位置显示成新的一列,然后将字符串截取出来,SQL如下:

WITH CTE1 AS (
SELECT ‘1‘ AS ID , ‘O3O,30,4834,348934,AA,09WOFJOWE,FW‘ AS STR
),
CTE2 AS (
SELECT 1 AS LEVEL,ID,STR,‘,‘ + STR + ‘,‘ AS STR_NEW,CHARINDEX(‘,‘,‘,‘ + STR + ‘,‘,1) AS POSITION
FROM CTE1
UNION ALL
SELECT LEVEL + 1 AS LEVEL,T.ID,T.STR,‘,‘ + T.STR + ‘,‘ AS STR_NEW,CHARINDEX(‘,‘,‘,‘ + T.STR + ‘,‘,POSITION + 1) AS POSITION
FROM CTE1 T JOIN CTE2 T1 ON T.ID = T1.ID
WHERE LEVEL < LEN(T.STR + ‘,‘) - ISNULL(LEN(REPLACE(T.STR + ‘,‘,‘,‘,‘‘)),0) + 1
)
SELECT *,SUBSTRING(STR_NEW,POSITION + 1,LEAD(POSITION)OVER(ORDER BY POSITION) - (POSITION + 1)) AS JQ FROM CTE2 ;

但是大家发现了,最后有一个空行,这个空的数据我们其实是不需要的,所以SQL修改为如下:

WITH CTE1 AS (
SELECT ‘1‘ AS ID , ‘O3O,30,4834,348934,AA,09WOFJOWE,FW‘ AS STR
),
CTE2 AS (
SELECT 1 AS LEVEL,ID,STR,‘,‘ + STR + ‘,‘ AS STR_NEW,CHARINDEX(‘,‘,‘,‘ + STR + ‘,‘,1) AS POSITION
FROM CTE1
UNION ALL
SELECT LEVEL + 1 AS LEVEL,T.ID,T.STR,‘,‘ + T.STR + ‘,‘ AS STR_NEW,CHARINDEX(‘,‘,‘,‘ + T.STR + ‘,‘,POSITION + 1) AS POSITION
FROM CTE1 T JOIN CTE2 T1 ON T.ID = T1.ID
WHERE LEVEL < LEN(T.STR + ‘,‘) - ISNULL(LEN(REPLACE(T.STR + ‘,‘,‘,‘,‘‘)),0) + 1
),
CTE3 AS (
SELECT LEVEL,ID,STR,STR_NEW,POSITION,LEAD(POSITION)OVER(ORDER BY POSITION) AS POSITION_NEXT
FROM CTE2
)
SELECT *,SUBSTRING(STR_NEW,POSITION + 1,POSITION_NEXT - (POSITION + 1)) AS JQ  FROM CTE3
WHERE POSITION_NEXT IS NOT NULL ;

到此,我们所提的需求已经实现,大家可以自己测试一下吧,谢谢!

时间: 2024-08-28 20:39:08

SQLSERVER中WITH AS递归来实现ORACLE的INSTR函数以及固定分隔符字符串截取的相关文章

重写Oracle的wm_concat函数,自定义分隔符、排序

oracle中,wm_concat函数是一个聚合函数,和mysql中的group_concat函数类似,不过group_concat函数比较强大,可以定义分隔符和排序,当然所谓强大是相对的,这里假使我们不知道oracle中的over函数,也不知道listagg函数. 我们先来看看wm_concat函数能实现什么功能,通俗点==>列传行,如果不明白,请看下面截图(可以看到分隔符默认为','顺序也是杂乱的)          所以,接下来,我们开始重写wm_concat函数(需要注意和需要说明的地方

Oracle的instr函数

 转自:http://knowyouknowme.iteye.com/blog/554945 1.instr 在Oracle/PLSQL中,instr函数返回要截取的字符串在源字符串中的位置. 语法如下: instr( string1, string2 [, start_position [, nth_appearance ] ] ) string1 源字符串,要在此字符串中查找. string2 要在string1中查找的字符串. start_position 代表string1 的哪个位置开

工作问题总结一:由数据查询慢来浅谈下oracle中的like和instr函数的模糊查询效率问题

今天上午10点左右,boss告诉我们生产环境一客户在某功能下录入信息时,出现加载数据很慢的情况,因为严重影响了客户使用,就让我们赶紧查实原因,组长和我就根据领导提供的用户登录系统,找到出问题的那个功能,选择买方和银行信息后加载限额信息时组长的电脑出现的反应是浏览器卡死,我的电脑上是去趟厕所回来坐下来之后才加载出来,我靠3分钟左右的时间,崩溃!!!  赶紧查代码  经查询代码发现,加载的数据是从千万量级(有2321w余条)的表中查询,查询语句中使用了like操作符,经研究发现确实是因为查询的sql

Oracle中字符串截取常用方法总结

本文链接:https://blog.csdn.net/rongtaoup/article/details/82217740substr 函数:截取字符串语法:SUBSTR(string,start, [length]) string:表示源字符串,即要截取的字符串. start:开始位置,从1开始查找.如果start是负数,则从string字符串末尾开始算起. length:可选项,表示截取字符串长度. 示例: SELECT SUBSTR('Hello SQL!', 1) FROM dual -

【转】oracle的substr函数的用法

[转]oracle的substr函数的用法 oracle的substr函数的用法 取得字符串中指定起始位置和长度的字符串   substr( string, start_position, [ length ] ) 如:     substr('This is a test', 6, 2)     would return 'is'     substr('This is a test', 6)     would return 'is a test'     substr('TechOnThe

Oracle数据库实用函数

实用函数 DECODE 语法如下: DECODE(value, if1, then1, if2,then2,if3,then3, . . . else )  Value 代表某个表的任何类型的任意列或一个通过计算所得的任何结果.当每个value值被测试,如果value的值为if1,Decode 函数的结果是then1:如果value等于if2,Decode函数结果是then2:等等.事实上,可以给出多个if/then 配对.如果value结果不等于给出的任何配对时,Decode 结果就返回els

Thinkphp 模板中直接对数据处理 模板中使用函数 中文字符串截取

1.Thinkphp 模板中直接对数据处理:{$data.name|substr=0,3} 2.中文字符串截取函数:mb_substr=0,14,'utf-8' 3.中文字符串统计:iconv_strlen(字符串,"UTF-8") <div style="margin-bottom: 8px;"> <a href="#" target="_blank" class="my_a" >

SqlServer中创建Oracle连接服务器

转自太祖元年的:http://www.cnblogs.com/jirglt/archive/2012/06/10/2544025.html参考:http://down.51cto.com/data/910072SqlServer中创建Oracle连接服务器 第一种:界面操作 (1)展开服务器对象-->链接服务器-->右击“新建链接服务器”(2)输入链接服务器的IP (3)链接成功后 第二种:语句操作 注:需要提前安装Oracle客户端程序,重启机器.(如果没有Oracle客户端程序,提示“未找

在oracle,mysql,sqlserver中,对要求取表的行数的语法格式

在oracle中如果我们要求取表的前几行,用关键字rownum 例: select * from student where rownum<=10 得出的结果是取出student表中的前10行 在mysql中,用关键字limit 例:select * from student limit 10 得出的结果是取出前10行数据 或    select * from student limit 1,2 表示从第一行后的两行数据,即取出的是第二行与第三行数据 在sqlserver中,用关键字top 例: