SQL Server使用REPLACE函数替换跨越多行的列中的值

时间:2017-04-25 20:05:08

标签: sql sql-server tsql sql-server-2016

我有一张这样的表:

Rule    | Mask       |Replacement
---------------------------------
@ # 12  | @          |[^0-9]
@ # 12  | #          |[0-9]

我构建了加入这两个表

表1

Mask_ID | Mask       |Replacement
---------------------------------
1       | @          |[^0-9]
2       | #          |[0-9]

表2

Rule_ID | Rule
--------------
1       | @ # 12

我想要的结果是:

Rule    | Expression
--------------------
@ # 12  | [^0-9] [0-9] 12

我一直在尝试使用REPLACE按钮来执行此操作,但我只能生成此结果

Rule    | Expression
--------------------
@ # 12  | [^0-9] # 12
@ # 12  | @ [0-9] 12

我不确定如何让REPLACE函数将多行应用于单行。如果有人有任何建议,我将不胜感激。

这是我到目前为止所做的,但它让我得到了上面提到的结果:

 SELECT 
  A.PointMask_CODE
  ,B.PointMasking_Rule_CODE
  ,B.Mask
  ,B.Escape_Character
  ,B.EscapedMaskRule
  ,REPLACE(A.PointMask_CODE, B.Mask, B.EscapedMaskRule)
 FROM
 tblStatusPointMasks_CORE A
 LEFT JOIN
 vwAORs_Status_PointMasks_EscapedRules B
 ON
 PointMask_CODE LIKE '%' + B.EscapedMask + '%' ESCAPE ISNULL(B.Escape_Character, '\')

enter image description here

2 个答案:

答案 0 :(得分:3)

对于给定的示例数据,您可以使用递归common table expression (cte)

create table masks (mask_id int, mask varchar(32), replacement varchar(32));
insert into masks values
 (1, '@', '[^0-9]')
,(2, '#', '[0-9]');

create table rules (rule_id int, rule_txt varchar(32));
insert into rules values
 (1, '@ # 12');

with cte as (
  select 
      r.rule_id
    , r.rule_txt
    , masks = 0
  from rules r
  union all 
  select 
      r.rule_id  
    , rule_txt = convert(varchar(32),replace(r.rule_txt,m.mask,m.replacement))
    , masks = r.masks+1
  from masks m
    inner join cte r
      on r.rule_txt like '%'+m.mask+'%'
)
select top 1 * 
from cte
order by masks desc

rextester演示:http://rextester.com/KAV58392

返回:

+---------+-----------------+-------+
| rule_id |    rule_txt     | masks |
+---------+-----------------+-------+
|       1 | [^0-9] [0-9] 12 |     2 |
+---------+-----------------+-------+

答案 1 :(得分:0)

还有一个选项,使用字符串操作...

create table masks (mask_id int, mask varchar(32), replacement varchar(32));
insert into masks values
 (1, '@', '[^0-9]')
,(2, '#', '[0-9]');

create table rules (rule_id int, rule_txt varchar(32));
insert into rules values
 (1, '@ # @ # 12');

declare @Table Table (charval varchar(10))
declare @char varchar(10), @rule_txt varchar(50)
select @rule_txt=rule_txt FROM rules
while charindex(' ',@rule_txt)>0
begin
    select @char=substring(@rule_txt,1,charindex(' ',@rule_txt)-1)
    FROM rules
    insert into @Table values (@char)
    SET @rule_txt=RIGHT(@rule_txt,(len(@rule_txt)-charindex(' ',@rule_txt)))
END
insert into @Table values (@rule_txt)
select stuff((SELECT ' '+isnull(replacement,charval)
 from @Table T left join masks M on M.mask=T.charval
  for xml path('')),1,1,'')
drop table rules
drop table masks