从逗号分隔的字符串SQL Server中删除值

时间:2018-01-10 17:40:37

标签: sql sql-server tsql

假设我有一个以逗号分隔的字符串(我知道,最好将其标准化,但它不是一个选项)并且记录看起来像这样(注意每个逗号后的空格):

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。

4 个答案:

答案 0 :(得分:4)

如果您完全确定无法修复这个糟糕的数据库设计,那么您可以使用CTEREPLACESTUFF

首先,创建并填充样本表(在将来的问题中保存此步骤):

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

See a live demo on rextester.

更新

您可以将原始列添加到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, '')
                , '') 

Here is the live demo for this.

答案 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;