我正在运行一个查询,向我显示某些项目的ID。我知道每个项目的描述。因此,我有2列运行查询
Select
IdItem,
case
when IdItem = 'I'
then 'Injection'
when IdItem = 'P'
then 'Pill'
when IdItem = 'DI'
then 'DIU'
when IdItem = 'F'
then 'AQVF'
when IdItem = 'M'
then 'AQVM'
when IdItem = 'O'
then 'Other'
else 'Not Defined'
end as 'Description'
from
dbo.Items
问题是我的结果有时会向我展示一个逗号分开的结果。
类似的东西:
IdItem | Description
---------+------------
P | Pill
M, O | Not Defined
DI | DIU
M, P, DI | Not Defined
结果显示了描述未定义的,由于其他原因,结果是否有这样的方法。
IdItem | Description
---------+----------------
P | Pill
M, O | AQVM, Other
DI | DIU
M, P, DI | AQVM, Pill, DIU
我必须对字符串使用替换,或者必须在外壳上制作每个组合
Select IdItem
, case
when IdItem = 'I'
then 'Injection'
when IdItem = 'P'
then 'Pill'
when IdItem = 'DI'
then 'DIU'
when IdItem = 'F'
then 'AQVF'
when IdItem = 'M'
then 'AQVM'
when IdItem = 'O'
then 'Other'
when IdItem = 'M, O'
then 'AQVM, Other'
when IdItem = 'M, P, DI'
then 'AQVM, Pill, DIU'
when IdItem = ...all other combinations
then ...results
else 'Not Defined'
end
as 'Description'
from dbo.Items
这些操作通常用一个使用定义的定界符拆分字符串值的函数来解决。如果您不在SQL Server 2016 上,并且无法使用string_split
中的内置,则必须自己滚动。我个人使用:
create function [dbo].[StringSplit]
(
@str nvarchar(4000) = ' ' -- String to split.
,@delimiter as nvarchar(1) = ',' -- Delimiting value to split on.
,@num as int = null -- Which value to return.
)
returns table
as
return
( -- Start tally table with 10 rows.
with n(n) as (select n from (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n(n))
-- Select the same number of rows as characters in @str as incremental row numbers.
-- Cross joins increase exponentially to a max possible 10,000 rows to cover largest @str length.
,t(t) as (select top (select len(@str) a) row_number() over (order by (select null)) from n n1,n n2,n n3,n n4)
-- Return the position of every value that follows the specified delimiter.
,s(s) as (select 1 union all select t+1 from t where substring(@str,t,1) = @delimiter)
-- Return the start and length of every value, to use in the SUBSTRING function.
-- ISNULL/NULLIF combo handles the last value where there is no delimiter at the end of the string.
,l(s,l) as (select s,isnull(nullif(charindex(@delimiter,@str,s),0)-s,4000) from s)
select rn as ItemNumber
,Item
from(select row_number() over(order by s) as rn
,substring(@str,s,l) as item
from l
) a
where rn = @num -- Return a specific value where specified,
or @num is null -- Or the everything where not.
)
使用如下:
declare @Items table(IdItem nvarchar(50));
insert into @Items values('P'),('M, O'),('DI'),('M, P, DI, ZZZ'),('ZZZ');
declare @ItemDescripions table(ItemId nvarchar(50),ItemDescription nvarchar(50));
insert into @ItemDescripions values('I' ,'Injection'),('P' ,'Pill'),('DI','DIU'),('F' ,'AQVF'),('M' ,'AQVM'),('O' ,'Other');
select IdItem
,ltrim(rtrim(s.Item)) as Item
,isnull(d.ItemDescription,'Not Defined') as ItemDescription
from @Items i
outer apply dbo.StringSplit(i.IdItem,',',null) s
left join @ItemDescripions d
on(ltrim(rtrim(s.Item)) = d.ItemId);
输出:
+---------------+------+-----------------+
| IdItem | Item | ItemDescription |
+---------------+------+-----------------+
| P | P | Pill |
| M, O | M | AQVM |
| M, O | O | Other |
| DI | DI | DIU |
| M, P, DI, ZZZ | M | AQVM |
| M, P, DI, ZZZ | P | Pill |
| M, P, DI, ZZZ | DI | DIU |
| M, P, DI, ZZZ | ZZZ | Not Defined |
| ZZZ | ZZZ | Not Defined |
+---------------+------+-----------------+
如果您想与问题中的问题完全输出ItemDescription
值(我建议不要在不将数据存储在分界列表中存储数据的最佳实践(,您可以使用con stuff
和 for xml
Combo而是:
select i.IdItem
,stuff((select ', ' + isnull(d.ItemDescription,'Not Defined')
from dbo.StringSplit(i.IdItem,',',null) s
left join @ItemDescripions d
on(ltrim(rtrim(s.Item)) = d.ItemId)
order by s.ItemNumber
for xml path('')
)
,1,2,'') as ItemDescription
from @Items i;
输出:
+---------------+------------------------------+
| IdItem | ItemDescription |
+---------------+------------------------------+
| P | Pill |
| M, O | AQVM, Other |
| DI | DIU |
| M, P, DI, ZZZ | AQVM, Pill, DIU, Not Defined |
| ZZZ | Not Defined |
+---------------+------------------------------+