原文:T-SQL技巧收集——拆分字符串

在开发中,很多时候都需要处理拆分字符串的操作。下面收集了几种方法供大家分享,其中的逗号可以改为多种有需要的符号,但是不能针对多种符号同时存在的例子。有待各位补充:

说明:

将字符串转换为正规化的数据表,可以使用多种方法实现,比如前端程序处理、游标、数据库循环函数,都是常用的技巧。

对于处理这些问题,比较好的思路就是使用SUBSTRING函数取出字符串,然后使用CHARINDEX函数定位。最后搭配排序函数完成拆分。

对于2005以后,可以使用CTE来实现。另外可以自定义一个函数处理。搭配输入分隔符与字符串,然后以TABLE方式返回。

解决方法:

下面是这4种方式的示例:

备注:首先针对原始字符串,可以使用BULKINSERT 后者BCP命令甚至直接INSERT语句,把原始数据导入数据表。以下语句是待处理的数据产生脚本,有业务代号和业务员订单:

为了输出每个业务员的每笔订单序号,所以用循环产生一个数据表,储存指定数量的序号。

接下来就是上面提到的4种方式的实现:

USE tempdb

GO

--建立数据表存储原始数据:

CREATE TABLE
Arrays

(

salesID
VARCHAR(10)
NOT NULL
,

salesOrd
VARCHAR(8000)
NOT NULL

)

GO

--注意:下面insert
语句中逗号后面有一个空格

INSERT 
INTO Arrays

VALUES (
'A',
'20, 223, 2544' )
;

INSERT 
INTO Arrays

VALUES (
'B',
'30, 23433, 28' )
;

INSERT 
INTO Arrays

VALUES (
'C',
'12, 10' ) ;

INSERT 
INTO Arrays

VALUES (
'D',
'4, 6, 45678, 2' )
;

GO

--通过循环产生存储指定数量的序号的表

CREATE TABLE
Nums

(

c1
INT NOT NULL

PRIMARY
KEY

) ;

GO

--产生数据

DECLARE
@i INT

SET @i
= 1

WHILE @i
<= 8000

BEGIN

INSERT 
INTO Nums

VALUES  (
@i )

SET
@i = @i
+ 1

END

以上版本使用。使用ROW_NUBMER函数

SELECT 
salesID [业务编号]
,

ROW_NUMBER()
OVER (
PARTITION BY salesID
ORDER BY
c1 ) AS
[序号]
,

SUBSTRING(salesOrd,
c1,
CHARINDEX(', ',
salesOrd +
', ', c1)
- c1)
AS [值]

FROM   
Arrays

JOIN
Nums ON c1
<= LEN(salesOrd)

ANDSUBSTRING(', '
+ salesOrd,
c1, 1)
= ', '

ORDER BY
salesID ,

[序号]

--方法二:适用于任何版本

SELECT 
salesID [业务编号]
,

c1
- LEN(REPLACE(LEFT(salesOrd,
c1),
', ', ''))
+ 1 [序号]
,

SUBSTRING(salesOrd,
c1,
CHARINDEX(', ',
salesOrd +
', ', c1)
- c1)
AS [值]

FROM   
arrays

JOIN
Nums ON c1
<= LEN(salesOrd)

ANDSUBSTRING(', '
+ salesOrd,
c1, 1)
= ', '

ORDER BY
salesID ,

[序号]

以上版本,使用CTE实现:

;

WITH   
SplitCTE

AS (
SELECT   salesID
,

1 AS
pos ,

1 AS
startpos ,

CHARINDEX(', ',
salesOrd +
', ') - 1
AS endpos

FROM    dbo.Arrays

WHERE   LEN(salesOrd)
> 0

UNION
ALL

SELECT  Prv.salesID
,

Prv.pos+ 1
,

Prv.endpos+ 2
,

CHARINDEX(', ',
CUR.salesOrd
+ ', ',
Prv.endpos
+ 2)

- 1

FROM    SplitCTE
ASPrv

JOIN
dbo.Arrays
AS Cur
ON CUR.salesID
= Prv.salesID

AND
CHARINDEX(', ',

cur.salesOrd

+
', ',

Prv.endpos
+ 2)
> 0

)

SELECT 
A.salesID
AS [业务编号]
,

pos
[序号]
,

CAST(SUBSTRING(salesOrd,
startpos,
endpos - startpos
+ 1)
AS INT)
AS [值]

FROM   
dbo.Arrays
AS a

JOIN
SplitCTEAS S
ON S.salesID
= A.salesID

ORDER
BY A.salesID
,

pos

GO

:使用自定义函数

CREATE FUNCTION
dbo.fn_split(
@orders AS
VARCHAR(MAX)
)

RETURNS
TABLE

AS

RETURN

SELECT 
c1 - LEN(REPLACE(LEFT(@orders,
c1),
', ', ''))
+ 1 AS
[序号]
,

SUBSTRING(@orders,
c1,
CHARINDEX(', ',
@orders +
', ', c1)
- c1)
AS [值]

FROM   
dbo.Nums

WHERE  
c1 <= LEN(@orders)

AND
SUBSTRING(', '
+ @orders,
c1, 1)
= ', '
;

GO

--然后使用cross apply技巧,合并分解字符串

SELECT 
salesID ,

B.*

FROM   
Arrays a

CROSS
APPLY dbo.fn_split(a.salesOrd)
b

GO

通过一下执行计划的开销可以看到CTE方法的实现开销最小,所以建议使用这种方式处理:

T-SQL技巧收集——拆分字符串的更多相关文章

  1. 【SQL】sql版Split函数。用于拆分字符串为单列表格

    功能与.net版string.Split函数类似,只不过.net返回的是数组,这个返回的是一个单列表格,每个拆分出来的子串占一行.可选是否移除空格子串和重复项.市面上类似的函数不算少,但大多都是在循环 ...

  2. oracle11g 拆分字符串的详细技巧

    转自:http://m.blog.csdn.net/article/details?id=51946573 <-->功能需求                 有一个比较长的SQL语句,查询 ...

  3. 在论坛中出现的比较难的sql问题:38(字符拆分 字符串检索问题)

    原文:在论坛中出现的比较难的sql问题:38(字符拆分 字符串检索问题) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得 ...

  4. 在论坛中出现的比较难的sql问题:27(字符串拆分、字符串合并、非连续数字的间隔范围、随机返回字符串)

    原文:在论坛中出现的比较难的sql问题:27(字符串拆分.字符串合并.非连续数字的间隔范围.随机返回字符串) 在论坛中看到一个帖子,帖子中有一些sql方面的面试题,我觉得这些面试题很有代表性. 原帖的 ...

  5. 在论坛中出现的比较难的sql问题:25(字符串拆分3)

    原文:在论坛中出现的比较难的sql问题:25(字符串拆分3) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必要记录下 ...

  6. 在论坛中出现的比较难的sql问题:12(递归问题2 拆分字符串)

    原文:在论坛中出现的比较难的sql问题:12(递归问题2 拆分字符串) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有 ...

  7. SQL中拆分字符串substr及统计字符出现频数replace用法实例讲解

    一.拆分字符串为若干行 例一:要求将表emp中的'king'按照每行一个单词拆成四行 注意:substr(str,pos):截取pos位置开始的字符: substr(str,pos,len):从pos ...

  8. MySQL基础操作&&常用的SQL技巧&&SQL语句优化

    基础操作     一:MySQL基础操作         1:MySQL表复制             复制表结构 + 复制表数据             create table t3 like t ...

  9. DelphiXE2 DataSnap开发技巧收集

    DelphiXE2 DataSnap开发技巧收集 作者:  2012-08-07 09:12:52     分类:Delphi     标签: 作为DelphiXE2 DataSnap开发的私家锦囊, ...

随机推荐

  1. SCSI miniport 驾驶一个简单的框架

    前段时间,只需用一台新电脑,由于资金有限没有匹配了心仪已久的SSD.我没感觉到飞翔的感觉,总不甘心,仔细想想.我死了相当大的存储,我们可以假设部分内存作为硬盘驱动器把它弄出来.不会比固态硬盘的速度快, ...

  2. python学习之list

    list: 创建:list = [5,7,9] 取值和改值:list[1] = list[1] * 5 列表尾插入:list.append(4) 去掉第0个值并返回第0个值的数值:list.pop(0 ...

  3. UNIX网络编程卷1 时间获取程序server TCP 协议相关性

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 最初代码:  这是一个简单的时间获取server程序.它和时间获取程序client一道工作. ...

  4. JAVA先进-设置(1)

    >Arrays 基本阵列 1.常见的数组产生于main() 函数,数组下标的索引不能超过0到int的范围 2.当程序试图訪问数组的第一个或者最后一个数据的时候,会发生ArrayIndexOutO ...

  5. 设计模式C++达到 3.抽象工厂

    简单工厂模式和工厂模式 要求 同类型的产品子类有共同的方法.这限制了产品子类的扩展.抽象工厂能client它提供了一个接口,它是client而不必指定产品的详细信息.创建多个产品系列产品对象.在归为一 ...

  6. 对HGE游戏引擎的一次封装

    HGE游戏引擎是一个开源2D游戏引擎,基于directX. 它的渲染及逻辑是基于帧回调的框架模式, 其提供一些主要的图像操作和输入控制功能. 我在之前写一个2D游戏的时候对它整个框架进行了一次封装,非 ...

  7. vs2015 安装问题汇总

    1. The product version that you are trying to set up is earlier than the version already installed o ...

  8. JavaScript动态更改页面元素

    通过JavaScript动态变化HTML元素 至HTML加元 首先需要创建一个标签,然后添加到标签中的相应的内容.然后创建添加到相应的位置好标签. <!DOCTYPE html PUBLIC & ...

  9. 解决 - java.lang.OutOfMemoryError: unable to create new native thread

    工作中碰到过这个问题好几次了,觉得有必要总结一下,所以有了这篇文章,这篇文章分为三个部分:认识问题.分析问题.解决问题. 一.认识问题: 首先我们通过下面这个 测试程序 来认识这个问题: 运行的环境  ...

  10. 【原创】leetCodeOj --- Factorial Trailing Zeroes 解题报告

    原题地址: https://oj.leetcode.com/problems/factorial-trailing-zeroes/ 题目内容: Given an integer n, return t ...