例如,我有一张这样的表,
ID Name
1 Apple,banana
2 Grape,Orange
3 Papaya,Jackfruit
我需要拆分(,)
并在SQL
ID Name Name2
1 Apple banana
2 Grape Orange
3 Papaya Jackfruit
答案 0 :(得分:2)
在SQL Server 2016之前分割字符串的最快,最可扩展的方法是编写一个分割字符串的SQLCLR方法,如this one。 SQL Server 2016引入了STRING_SPLIT
函数,速度更快。
在SQL Server 2016之前为版本拆分字符串的第二种最快方法是将分离的文本转换为XML并使用XML运算符来检索单个项目。典型用法,如Aaron Bertrand's articles所示,将项目作为行返回。它可以很容易地调整为以列为单位返回项目:
declare @table table (ID int, Name nvarchar(200))
insert into @table
values
(1,'Apple,banana'),
(2,'Grape,Orange'),
(3,'Papaya,Jackfruit');
with items as (
select
ID,
xmlField= cast('<item><tag>'
+ replace(Name,',','</tag><tag>')
+ '</tag></item>' as xml)
from @table
)
-- Step 2: Select different tags and display them as fields
select
y.item.value('(tag/text())[1]','nvarchar(20)') As Name1,
y.item.value('(tag/text())[2]','nvarchar(20)') as Name2
from items outer apply xmlField.nodes('item') as y(item)
返回:
1 Apple banana
2 Grape Orange
3 Papaya Jackfruit
这首先将Name1,Name2
转换为<item><tag>Name1</tag><tag>Name2</tag><item>
,然后将其转换为XML并作为xmlField返回。
outer apply xmlField.nodes('item') as y(item)
将此字段转换为名为y
的项目表。每个字段中只存在一个item
行。
最后,y.item.value('(tag/text())[1]','nvarchar(20)')
将第一个标记元素的 text 提取为Name1。
这可以很容易地扩展到多个条目,或者将条目作为不同的元素返回。
必须事先知道列数。 SQL(该语言)不允许任意数量的列。如果不同的字段包含不同数量的标记,则必须将它们作为行返回。
在这种情况下,如果您的目标是SQL Server 2016或XML拆分技术的原始版本,则应使用STRING_SPLIT:
CREATE FUNCTION dbo.SplitStrings_XML
(
@List nvarchar(max),
@Delimiter nvarchar(10)
)
RETURNS TABLE WITH SCHEMABINDING
AS
RETURN (SELECT [value] = y.i.value('(./text())[1]', 'varchar(8000)')
FROM (SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i));
值得检查Performance Surprises and Assumptions : STRING_SPLIT(),它会比较所有可用的字符串拆分技术,以找到最快和最可扩展的
答案 1 :(得分:0)
我们通过使用超前和滞后函数以及拆分字符串来获得结果并将结果集插入到您需要的表中
IF OBJECT_ID('tempdb..#InsertTable') IS NOT NULL
DROP TABLE #InsertTable
DECLARE @table TABLE (ID INT, Name VARCHAR(50))
CREATE TABLE #InsertTable (ID INT,Name1 VARCHAR(100),Name2 VARCHAR(100))
INSERT INTO @table
SELECT 1,'Apple,Banana' UNION ALL
SELECT 2,'Grape,Orange' UNION ALL
SELECT 3,'Papaya,Jackfruit'
INSERT INTO #InsertTable(ID,Name1,Name2)
SELECT DISTINCT ID,
ISNULL(Name1,LagName1) AS Name1 ,
ISNULL(Name2,LeadName2) AS Name2
FROM
(
SELECT ID,
Name1,
LAG(NAme1,1)OVER(ORDER BY ID) LagName1,
Name2,
LEAD(Name2,1)OVER(ORDER BY ID)LeadName2
FROM
(
SELECT ID, CASE WHEN Seq%2=1 THEN Name END AS Name1,
CASE WHEN Seq%2=0 THEN Name END AS Name2
FROM
(
SELECT Row_NUmber ()OVER(ORDER BY ID )AS Seq,ID, Split.a.value('.', 'VARCHAR(1000)') AS Name
FROM (
SELECT ID, CAST('<S>' + REPLACE(Name, ',', '</S><S>') + '</S>' AS XML) AS Name
FROM @table
) AS A
CROSS APPLY Name.nodes('/S') AS Split(a)
)Dt
)DT2
)Final
SELECT * FROM #InsertTable
结果
ID Name1 Name2
----------------------
1 Apple Banana
2 Grape Orange
3 Papaya Jackfruit