如何拆分多个字符串并插入SQL Server FN\u SplitStr

如何拆分多个字符串并插入SQL Server FN\u SplitStr,sql,sql-server,Sql,Sql Server,我有两个字符串和一个整数: @categoryID int = 163, @Ids nvarchar(2000) = '1,2,3', @Names nvarchar(2000) = 'Bob,Joe,Alex' 我需要选择3列3行;完成最多的是3行2列: select @categoryID,items from FN_SplitStr(@Ids,',') 结果: 163,1 163,2 163,3 但我不知道如何拆分这两个字符串 我尝试了很多方法,比如: select @categor

我有两个字符串和一个整数:

@categoryID int = 163,
@Ids nvarchar(2000) = '1,2,3',
@Names nvarchar(2000) = 'Bob,Joe,Alex'
我需要选择3列3行;完成最多的是3行2列:

select @categoryID,items from FN_SplitStr(@Ids,',')
结果:

163,1
163,2
163,3
但我不知道如何拆分这两个字符串

我尝试了很多方法,比如:

select @categoryID,items from FN_SplitStr((@Ids,@Names),',')
select @categoryID,items from FN_SplitStr(@Ids,','),items from FN_SplitStr(@Names,',')
预期产出:

163,1,Bob
163,2,Joe
163,3,Alex
注1:我看了几十个问题,最相似的是: 但这个问题是不同的


注2:FN_SplitStr是用于在SQL中拆分字符串的函数。我正在尝试创建一个存储过程。

在您的存储过程中,对@id进行字符串拆分,并插入到temp1表中,其中标识为1,1列。您将获得:

163,1,1
163,2,2
163,3,3
Bob,1
Joe,2
Alex,3
然后对@Names执行第二个字符串拆分,并将其插入到temp2表中,其中标识为1,1列。您将获得:

163,1,1
163,2,2
163,3,3
Bob,1
Joe,2
Alex,3
然后可以在temp1.rowid=temp2.rowid上使用temp1和temp2进行内部联接,并获得:

163,1,Bob
163,2,Joe
163,3,Alex

我希望这能解决您的问题。

根据您的预期输出,您必须使用交叉应用两次,然后创建某种排序,以确保获得正确的值。由于ID和名称似乎没有任何关系,当您将字符串拆分为名称和ID时,交叉应用将创建多行

可能有更好的方法,但这也会给出您的预期输出。您可以将此字符串拆分更改为本地函数

第一个密集等级是确保我们得到三个唯一的名称,第二个密集等级是基于order by和ID的名称内的等级,在子查询之外,您必须进行一些比较,以仅获得3行

Declare @categoryID int = 163,
@Ids nvarchar(2000) = '1,2,3',
@Names nvarchar(2000) = 'Bob,Joe,Alex' 

select ConcatenatedValue, CategoryID, IDs, Names from (
select    concat(@categoryID,',',a.value,',',b.value) ConcatenatedValue, @categoryID CategoryID, 
A.value as IDs, b.value  as Names , DENSE_RANK() over (order by b.value) as Rn, 
DENSE_RANK() over (partition by b.value order by a.value) as Ranked  
from  string_split(@IDs,',') a 
cross apply string_split(@names,',') B ) t
where Rn - Ranked = 0 
输出:


可以使用递归CTE执行此操作:

with cte as (
      select @categoryId as categoryId,
             convert(varchar(max), left(@ids, charindex(',', @ids + ',') - 1)) as id,
             convert(varchar(max), left(@names, charindex(',', @names + ',') - 1)) as name,
             convert(varchar(max), stuff(@ids, 1, charindex(',', @ids + ','), '')) as rest_ids,
             convert(varchar(max), stuff(@names, 1, charindex(',', @names + ','), '')) as rest_names
      union all
      select categoryId,
             convert(varchar(max), left(rest_ids, charindex(',', rest_ids + ',') - 1)) as id,
             convert(varchar(max), left(rest_names, charindex(',', rest_names + ',') - 1)) as name,
             convert(varchar(max), stuff(rest_ids, 1, charindex(',', rest_ids + ','), '')) as rest_ids,
             convert(varchar(max), stuff(rest_names, 1, charindex(',', rest_names + ','), '')) as rest_names
      from cte
      where rest_ids <> ''
     )
select categoryid, id, name
from cte;

是一个dbfiddle。

您需要将CSV值与记录编号拆分。为此,您需要使用ROW_NUMBER函数生成记录方式的唯一ID,如RID列,同时在行中拆分CSV列。 您可以使用表值拆分函数或XML,如下所示

请检查此项,让我们知道您的解决方案是否找到

DECLARE
    @categoryID int = 163,
    @Ids nvarchar(2000) = '1,2,3',
    @Names nvarchar(2000) = 'Bob,Joe,Alex'

SELECT 
    @categoryID AS categoryID,
    q.Id,
    w.Names
FROM
(
    SELECT
        ROW_NUMBER() OVER (ORDER BY f.value('.','VARCHAR(10)')) AS RID, 
        f.value('.','VARCHAR(10)') AS Id
    FROM
    (
        SELECT 
            CAST('<a>' + REPLACE(@Ids,',','</a><a>') + '</a>' AS XML) AS idXML
    ) x
    CROSS APPLY x.idXML.nodes('a') AS e(f)
) q
INNER JOIN
(
    SELECT
        ROW_NUMBER() OVER (ORDER BY h.value('.','VARCHAR(10)')) AS RID,
        h.value('.','VARCHAR(10)') AS Names
    FROM
    (
        SELECT
            CAST('<a>' + REPLACE(@Names,',','</a><a>') + '</a>' AS XML) AS namesXML
    ) y
    CROSS APPLY y.namesXML.nodes('a') AS g(h)
) w ON w.RID = q.RID

163,1 163,2 163,3这是您的预期输出吗?@Avi用“T预期输出”更新了问题谢谢您提醒我