如何拆分多个字符串并插入SQL Server FN_SplitStr

时间:2019-08-23 23:41:22

标签: sql sql-server

我有2个字符串和1个整数:

@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::我查看了数十个最相似的问题: How to split string and insert values into table in SQL ServerSQL Server : split multiple strings into one row each,但这个问题有所不同。

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

4 个答案:

答案 0 :(得分:1)

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

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

第一个密集等级是为了确保我们得到三个唯一的名称,第二个密集等级是名称内根据ID和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 

输出:

enter image description here

答案 1 :(得分:0)

在您的存储过程中,对@Ids进行字符串分割,然后插入带有IDENTITY(1,1)列的#temp1表中。您将获得:

163,1,1
163,2,2
163,3,3

然后执行@Names的第二个字符串拆分,并插入带有IDENT(1,1)列的#temp2表。您将获得:

Bob,1
Joe,2
Alex,3

然后可以在#temp1.rowid =#temp2.​​rowid上使用#temp1和#temp2进行内部联接,并获得:

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

我希望这可以解决您的问题。

答案 2 :(得分: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;

Here是db <>小提琴。

答案 3 :(得分:0)

您需要用记录号分割CSV值。为此,在将CSV列拆分为行时,您需要使用ROW_NUMBER()函数生成明智的唯一ID作为“ RID”之类的列。 您可以使用表值拆分功能或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
相关问题