如何以基于集合的方式解析逗号分隔值?
How to resolve comma separated values in a set based manner?
我有一个主 table,其中包含每个 ID 的逗号分隔代码:
create table main (id int, codes nvarchar(3))
id codes
1 HIR, RES, NAS
2 TA1, WQ9, PLM
以及描述这些代码含义的查找 table:
create table lookup (code nvarchar(3), description nvarchar(100))
code description
HIR High Rise
NAS Mobile Home
PLM Proposed Attached
...
我想从主 table select 并将逗号分隔的代码列表替换为相应描述的逗号分隔列表:
id codes
1 High Rise, Residential, Mobile Home
我想出了如何遍历每一行、分解 CSV、手动查询每一行、重新构建字符串并生成我想要的内容的方法。
但是,有没有一种方法可以以基于集合的方式(并且更快)做到这一点?
对于主要的 table,您将要进行交叉应用 STRING_SPLIT 然后您可以将其加入您的查找 table 并使用 stuff() 和 for xml
您可以在此处了解交叉应用 STRING_SPLIT(2016 春夏):
Turning a Comma Separated string into individual rows(列出其他方法)
您可以在此处学习有关 xml 的内容:
Convert multiple rows into one with comma as separator
因为你是 2016 年,一个选项是 string_split,但没有维护序列的 gtd。也许这会有所帮助
例子
Select A.ID
,Codes = B.S
From Main A
Cross Apply (
Select S = stuff((Select ', ' +[description]
From (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(100)')))
From (Select x = Cast('<x>' + replace((Select replace(A.[codes],',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) B1
Join Lookup B2 on B1.RetVal=B2.code
Order by RetSeq
For XML Path (''))
,1,2,'')
) B
Returns
ID Codes
1 High Rise, Mobile Home
2 Proposed Attached
注意项目丢失,因为查找不完整。
由于您可以使用 SQL Server 2017,所以 STRING_AGG()
:
select m.id, string_agg(l.description, ', ') within group (order by charindex(l.code, m.codes)) codes
from main m inner join lookup l
on concat(',', replace(m.codes, ', ', ','), ',') like concat('%', l.code, '%')
group by m.id
参见demo。
结果:
> id | codes
> -: | :----------------------------------
> 1 | High Rise, Residential, Mobile Home
我有一个主 table,其中包含每个 ID 的逗号分隔代码:
create table main (id int, codes nvarchar(3))
id codes
1 HIR, RES, NAS
2 TA1, WQ9, PLM
以及描述这些代码含义的查找 table:
create table lookup (code nvarchar(3), description nvarchar(100))
code description
HIR High Rise
NAS Mobile Home
PLM Proposed Attached
...
我想从主 table select 并将逗号分隔的代码列表替换为相应描述的逗号分隔列表:
id codes
1 High Rise, Residential, Mobile Home
我想出了如何遍历每一行、分解 CSV、手动查询每一行、重新构建字符串并生成我想要的内容的方法。
但是,有没有一种方法可以以基于集合的方式(并且更快)做到这一点?
对于主要的 table,您将要进行交叉应用 STRING_SPLIT 然后您可以将其加入您的查找 table 并使用 stuff() 和 for xml
您可以在此处了解交叉应用 STRING_SPLIT(2016 春夏): Turning a Comma Separated string into individual rows(列出其他方法)
您可以在此处学习有关 xml 的内容: Convert multiple rows into one with comma as separator
因为你是 2016 年,一个选项是 string_split,但没有维护序列的 gtd。也许这会有所帮助
例子
Select A.ID
,Codes = B.S
From Main A
Cross Apply (
Select S = stuff((Select ', ' +[description]
From (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(100)')))
From (Select x = Cast('<x>' + replace((Select replace(A.[codes],',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) B1
Join Lookup B2 on B1.RetVal=B2.code
Order by RetSeq
For XML Path (''))
,1,2,'')
) B
Returns
ID Codes
1 High Rise, Mobile Home
2 Proposed Attached
注意项目丢失,因为查找不完整。
由于您可以使用 SQL Server 2017,所以 STRING_AGG()
:
select m.id, string_agg(l.description, ', ') within group (order by charindex(l.code, m.codes)) codes
from main m inner join lookup l
on concat(',', replace(m.codes, ', ', ','), ',') like concat('%', l.code, '%')
group by m.id
参见demo。
结果:
> id | codes
> -: | :----------------------------------
> 1 | High Rise, Residential, Mobile Home