Sql server 将逗号分隔的字段拆分为大量行

Sql server 将逗号分隔的字段拆分为大量行,sql-server,tsql,Sql Server,Tsql,我试图将数据从一个模式迁移到另一个模式,但在拆分逗号分隔的字段时遇到了一些问题 S1:源数据库 S2:目标数据库 S1有一个名为ownerUserIDList的字段,该字段链接到S2中的AMID,问题是S2在此字段中只允许1个值,而S1可以有多个值,并且在数据库中以逗号分隔,因此我的计划是拆分字段,并使用拆分的最后一个元素更新S2 问题是它花费的时间太长,而且经常超时。该表大约有60万行。我已经尝试了一些我发现的方法,但是对于一个大的数据集来说,没有一种方法看起来真的那么快 下面的所有示例都将成

我试图将数据从一个模式迁移到另一个模式,但在拆分逗号分隔的字段时遇到了一些问题

S1:源数据库

S2:目标数据库

S1有一个名为ownerUserIDList的字段,该字段链接到S2中的AMID,问题是S2在此字段中只允许1个值,而S1可以有多个值,并且在数据库中以逗号分隔,因此我的计划是拆分字段,并使用拆分的最后一个元素更新S2

问题是它花费的时间太长,而且经常超时。该表大约有60万行。我已经尝试了一些我发现的方法,但是对于一个大的数据集来说,没有一种方法看起来真的那么快

下面的所有示例都将成为实际数据迁移的update语句,这些只是为了比较运行计时

方法1:

SELECT TOP 100000 CASE 
        WHEN ownerUserIDList LIKE '%,%' THEN SUBSTRING( ownerUserIDList , LEN(ownerUserIDList) -  CHARINDEX(',',REVERSE(ownerUserIDList)) + 2  , LEN(ownerUserIDList)  )
        ELSE ownerUserIDList
    END
FROM S1.UserTable WHERE ownerUserIDList != '' AND ownerUserIDList IS NOT NULL
SELECT TOP 100000 value 
FROM S1.UserTable
    CROSS APPLY STRING_SPLIT(ownerUserIDList, ',') 
    WHERE ownerUserIDList != '' AND ownerUserIDList IS NOT NULL
GO
SQL Server执行时间:CPU时间=2359毫秒,运行时间= 728479毫秒

方法2:

SELECT TOP 100000 CASE 
        WHEN ownerUserIDList LIKE '%,%' THEN SUBSTRING( ownerUserIDList , LEN(ownerUserIDList) -  CHARINDEX(',',REVERSE(ownerUserIDList)) + 2  , LEN(ownerUserIDList)  )
        ELSE ownerUserIDList
    END
FROM S1.UserTable WHERE ownerUserIDList != '' AND ownerUserIDList IS NOT NULL
SELECT TOP 100000 value 
FROM S1.UserTable
    CROSS APPLY STRING_SPLIT(ownerUserIDList, ',') 
    WHERE ownerUserIDList != '' AND ownerUserIDList IS NOT NULL
GO
SQL Server执行时间:CPU时间=1719毫秒,运行时间= 399817毫秒

考虑到我必须在多个甚至更大的表上运行类似的查询,这两种方法都非常慢。有没有其他方法可以更快地拆分这些字段

表格结构非常简单:

S1

UserID    ownerUserIDList   S2_AMID
---------------------------------------
1           20              1
2           20, 21, 23      4
3           21, 22, 23      4
AMID    S1_UserID
-----------------
1       20
2       21
3       22
4       23
S2

UserID    ownerUserIDList   S2_AMID
---------------------------------------
1           20              1
2           20, 21, 23      4
3           21, 22, 23      4
AMID    S1_UserID
-----------------
1       20
2       21
3       22
4       23

如果你真的只想要最后一个条目,试试这个。可以添加子句以避免空列表或单条目列表

declare @t table(UserID int, OwnerID varchar(50))
insert @t values (1,'1,2,3'),(2,'3,4,5'),(3,'6,7,8')
select *, left(reverse(ownerID),CHARINDEX(',',reverse(ownerID))-1) from @t

这是非常接近你的第一个选择,但我怀疑你会更接近。可能是CLI功能?我会让其他人来编写代码。

如果你真的只想要最后一个条目,试试这个。可以添加子句以避免空列表或单条目列表

declare @t table(UserID int, OwnerID varchar(50))
insert @t values (1,'1,2,3'),(2,'3,4,5'),(3,'6,7,8')
select *, left(reverse(ownerID),CHARINDEX(',',reverse(ownerID))-1) from @t

这是非常接近你的第一个选择,但我怀疑你会更接近。可能是CLI功能?我将让其他人来编写代码。

SQL Server不擅长处理字符串,如果您的主要目标是获得拆分字符串的最佳性能,您可以尝试使用
CLR
函数


您可以获得有关
CLR
函数的更多详细信息SQL Server不擅长处理字符串,如果您的主要目标是获得拆分字符串的最佳性能,您可以尝试
CLR
函数


您可以获得有关
CLR
函数的更多详细信息

在我没有时间学习CLR函数之前,我从未使用过这些函数,但感谢这一点,这将有助于今后的工作。在我没有时间学习这些函数之前,我从未使用过CLR函数,但感谢这一点,这将有助于今后的工作。这一点很有效,在稍微修改一下更新查询之后,创建链接花费了6秒钟。谢谢这很有效,在稍微修改一下更新查询后,创建链接需要6秒钟。谢谢