我認爲你需要先了解一下,爲什麼你認爲XML
方法不執行不夠好,您的需求,爲it has actually been shown to perform very well for larger input strings。
如果只需要處理的輸入串高達要麼4000或8000個字符(分別非max
nvarchar
和varchar
類型),則可以利用包含內嵌表值函數which will also perform very well內的帳簿表。我使用的版本可以在這篇文章的末尾找到。
利用這個功能,我們可以在你的InputLocations
柱拆分出來的價值觀,但我們仍然需要使用for xml
將它們串聯到一起爲你想要的格式:
-- Define data
declare @InputLocationTable table (SKUID int,InputLocations varchar(100),Flag varchar(100));
declare @Location table (SKUID int,Locations varchar(100));
insert into @InputLocationTable(SKUID,InputLocations) values (11,'Loc1, Loc2, Loc3, Loc4, Loc5, Loc6'),(12,'Loc1, Loc2'),(13,'Loc4,Loc5'),(14,'Loc1');
insert into @Location(SKUID,Locations) values (11,'Loc3'),(11,'Loc4'),(11,'Loc5'),(11,'Loc7'),(12,'Loc10'),(12,'Loc1'),(12,'Loc5'),(13,'Loc4'),(13,'Loc2'),(13,'Loc2'),(14,'Loc1');
--Query
-- Derived table splits out the values held within the InputLocations column
with i as
(
select i.SKUID
,i.InputLocations
,s.item as Loc
from @InputLocationTable as i
cross apply dbo.fn_StringSplit4k(replace(i.InputLocations,' ',''),',',null) as s
)
select il.SKUID
,il.InputLocations
,isnull('Add ' -- The split Locations are then matched to those already in @Location and those not present are concatenated together.
+ stuff((select ', ' + i.Loc
from i
left join @Location as l
on i.SKUID = l.SKUID
and i.Loc = l.Locations
where il.SKUID = i.SKUID
and l.SKUID is null
for xml path('')
)
,1,2,''
)
,'No Flag') as Flag
from @InputLocationTable as il
order by il.SKUID;
輸出:
+-------+------------------------------------+----------------------+
| SKUID | InputLocations | Flag |
+-------+------------------------------------+----------------------+
| 11 | Loc1, Loc2, Loc3, Loc4, Loc5, Loc6 | Add Loc1, Loc2, Loc6 |
| 12 | Loc1, Loc2 | Add Loc2 |
| 13 | Loc4,Loc5 | Add Loc5 |
| 14 | Loc1 | No Flag |
+-------+------------------------------------+----------------------+
對於nvarchar
輸入(我有不同的功能varchar
和max
類型輸入)這是我的版本的字符串分裂功能鏈接上面:
create function [dbo].[fn_StringSplit4k]
(
@str nvarchar(4000) = ' ' -- String to split.
,@delimiter as nvarchar(1) = ',' -- Delimiting value to split on.
,@num as int = null -- Which value in the list to return. NULL returns all.
)
returns table
as
return
-- Start tally table with 10 rows.
with n(n) as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1)
-- 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(isnull(@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(isnull(@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,isnull(@str,''),s),0)-s,4000) from s)
select rn
,item
from(select row_number() over(order by s) as rn
,substring(@str,s,l) as item
from l
) a
where rn = @num
or @num is null;
go
你的意思是說,更新的標誌的列,其中INputLocation不是位置表的位置scolumn –
我不知道如果我正確地理解你的問題......你說,你設法找到與XML解決方案但寧願避免使用它。那麼,「FOR XML PATH」afaik是直到SQL Server 2016執行字符串連接的最佳和推薦的解決方案。2016年,MSFT添加了STRING_AGG函數。在SQL Server 2008上,您可以使用自定義程序集作爲替代方案。但這有其不利之處。看看https://www.sqlshack.com/string-concatenation-done-right-part-2-an-effective-technique/。 –
嗨,感謝您的重播,我只是避免使用XML路徑,這並不意味着我不應該使用和所有,我使用的SQL服務器2014年,所以請建議我更好的代碼或答案爲 – Karthik