假设我有一个以逗号分隔的字符串(我知道,最好将其标准化,但它不是一个选项)并且记录看起来像这样(注意每个逗号后的空格):
11, 15, 17, 23
15, 34, 46, 69
15
27, 41, 29, 15
无论位置如何,我都需要从拥有它的所有值中删除“15”。如您所见,数字可以是字符串开头,中间和最后的唯一值。在我完成之后,我希望我的记录看起来像这样:
11, 17, 23
34, 46, 69
27, 41, 29
我知道我可以创建3-4个单独的查询来处理所有不同的情况,但是真的希望有1个查询。
TIA, -TS。
答案 0 :(得分:4)
如果您完全确定无法修复这个糟糕的数据库设计,那么您可以使用CTE,REPLACE
和STUFF
首先,创建并填充样本表(请在将来的问题中保存此步骤):
DECLARE @T AS TABLE
(
BadColumn varchar(100)
)
INSERT INTO @T VALUES
('11, 15, 17, 23'),
('15, 34, 46, 69'),
('15'),
('27, 41, 29, 15')
然后,CTE:注意我在实际值之前和之后添加分隔符。
;WITH CTE AS
(
SELECT REPLACE(', '+ BadColumn +', ', ', 15, ', ', ') As Without15
FROM @T
)
查询:(我已使用select来显示结果,但您也可以使用它来更新)
SELECT ISNULL(
STUFF(
STUFF(Without15, 1, 2, ''),
LEN(Without15)-2, 2, '')
, '') As StillBadButWithout15
FROM CTE
结果:
StillBadButWithout15
11, 17, 23
34, 46, 69
27, 41, 29
您可以将原始列添加到cte,只需直接更新cte:
;WITH CTE AS
(
SELECT BadColumn, REPLACE(', '+ BadColumn +', ', ', 15, ', ', ') As Without15
FROM @T
)
UPDATE CTE
SET BadColumn = ISNULL(
STUFF(
STUFF(Without15, 1, 2, ''),
LEN(Without15)-2, 2, '')
, '')
答案 1 :(得分:1)
如果您使用的是 SQL 2017,则可以使用 STRING_AGG 函数:
声明@valueToRemove varchar(2) = '15'
DECLARE @T AS TABLE (id int not null identity, BadColumn varchar(100))
插入@T 值 ('11, 15, 17, 23, 150'), ('15, 34, 46, 69'), ('15'), ('27, 41, 29, 15')
;结果为( select id as orgId, STRING_AGG(result.res, ',') as newVal from ( 选择 id, value as res from @T 交叉应用 string_split(BadColumn, ',') where trim(value) != @valueToRemove ) 按 id 分组的结果)
update @T set BadColumn = newVal from result where id = orgId
update @t set BadColumn = '' where trim(BadColumn) = @valueToRemove -- 如果更新是特定于 id 的,则不需要此
从@T 中选择 *
答案 2 :(得分:0)
与Zohar发布的内容类似 - 我有:
select BadColumn, GoodColumn =
case
when BadColumn like '15,%' then substring(BadColumn,4,8000)
when BadColumn like '%,15,%' then replace(BadColumn,',15','')
when badColumn like '%,15' then substring(BadColumn,1,datalength(badColumn)-3)
when badColumn = '15' then ''
else BadColumn
end
from (select BadColumn=rtrim(ltrim(replace(badColumn,' ',''))) from @t) map;
分裂器对此有点矫枉过正,但这就是解决方案的样子:
with cleanT as (select BadColumn = replace(badColumn,' ','') from @T)
select t.badColumn , cleanString = isnull(stuff(stringAgg.item,1,1,''),'')
from cleanT t
cross apply
(
select ','+[value]
from cleanT tx
cross apply string_split(t.BadColumn,',')
where t.BadColumn = tx.BadColumn
and [value] <> '15'
for xml path('')
) stringAgg(item);
答案 3 :(得分:0)
三个简单的更新,我怀疑比单个更新更有效
update table set col = REPLACE(col, ', 15', '');
update table set col = REPLACE(col, '15, ', '');
update table set col = null where col = 15;