使用SQL REPLACE,其中替换的字符串和替换是另一个替换的结果

时间:2016-10-12 08:00:33

标签: sql sql-server tsql replace

尝试替换我的数据库中的一些字符串,其中我有两个表。 table_2上的替换使用第一次替换的结果作为输入:

当前状态(字符串只是一个替身,它可以是任何东西,重要的部分是短划线):

|table_1 - col1|    |table_2   - col1            |       
----------------    ------------------------------
|string-1      |    |text string-1 text string-3 |     
|string-2      |    |text string-3 string-2 t-ext|
|string-3      |    |string-2 text string-3 te-xt|

期望的结果:

|table_1 - col1 |    |table_2 - col1              |       
-----------------    ------------------------------
|string_1       |    |text string_1 text string_3 |     
|string_2       |    |text string_3 string_2 t-ext|
|string_3       |    |string_2 text string_3 te-xt|

简单地说,我想将-替换为table_1中的_,并在table_2上执行相应的替换。

提出了第一部分,但我无法弄清楚table_2上的替换部分:

SELECT col1, REPLACE(col1, '-', '_') as Replacement  
FROM table_1 
where col1 like '%-%'

我需要做这样的事情(这段代码是INCORRECT):

SELECT REPLACE(col1, 
    SELECT [col1] FROM [table_1] where col1 like '%-%',
    SELECT REPLACE([col1], '-', '_') FROM [table_1] where col1 like '%-%')      
from table_2

4 个答案:

答案 0 :(得分:1)

不超过2个替换

def price(stock, start):
    price = web.DataReader(name=stock, data_source='yahoo', start=start)['Adj Close']
    return price.div(price.iat[0]).resample('M').last().to_frame('price')

a = price('SPY','2000-01-01')

v = a.pct_change().rolling(12).std().dropna().mul(200).astype(int)

def dyna_mean(x):
    end = a.index.get_loc(x.name)
    start = end - x.price
    return a.price.iloc[start:end].mean()

pd.concat([a.price, v.price, v.apply(dyna_mean, axis=1)],
          axis=1, keys=['price', 'vol', 'mean'])

答案 1 :(得分:1)

这完全是临时的,不需要递归:

DECLARE @table_1 TABLE(ID INT IDENTITY,col1 VARCHAR(100));
INSERT INTO @table_1 VALUES    
 ('string-1'),('string-2'),('string-3');

DECLARE @table_2 TABLE(ID INT IDENTITY,col1 VARCHAR(100));
INSERT INTO @table_2 VALUES    
 ('text string-1 text string-3'),('text string-3 string-2 t-ext'),('string-2 text string-3 te-xt');

- 第一个CTE替换了t1

中的值
WITH t1New AS
(
    SELECT ID AS t1_ID
          ,t1.col1 AS t1c1
          ,REPLACE(t1.col1,'-','_') AS new_t1c1 
    FROM @table_1 AS t1
)

- 第二个CTE在空白处拆分t2的字符串

,t2Splitted AS
(
    SELECT ID
          ,col1 AS t2c1
          ,CAST('<x>' + REPLACE(t2.col1,' ','</x><x>') + '</x>' AS XML) AS Casted
    FROM @table_2 AS t2
)

- 此CTE将值映射到拆分部分

,Mapped AS
(
    SELECT t1New.*
          ,t2Splitted.ID AS t2_ID 
          ,ROW_NUMBER() OVER(PARTITION BY t2Splitted.ID ORDER BY (SELECT NULL)) AS PartIndex
          ,part.value('.','nvarchar(max)') AS Part
    FROM t2Splitted
    CROSS APPLY t2Splitted.Casted.nodes('/x') AS A(part)
    LEFT JOIN t1New ON t1New.t1c1=part.value('.','nvarchar(max)')
)

- 如果有映射,则采用新值,否则采用旧值

,NewValues AS
(
    SELECT *
           ,CASE WHEN t1c1 IS NOT NULL THEN new_t1c1 ELSE Part END AS newValue
    FROM Mapped 
)

- 最终的CTE将字符串与原始顺序中的空格重新连接

,Final AS
(
    SELECT nv1.t2_ID
      ,(SELECT ' ' + nv2.newValue
        FROM NewValues AS nv2
        WHERE nv2.t2_ID=nv1.t2_ID
        ORDER BY PartIndex
        FOR XML PATH('')) AS FinalValue
    FROM NewValues AS nv1
    GROUP BY nv1.t2_ID
)

- 最后一个值用于更新原始表

UPDATE t2 SET t2.col1=Final.FinalValue
FROM @table_2 AS t2
INNER JOIN Final ON Final.t2_ID=t2.ID

你有什么要求:UPDATE t1,这是一个单行并摆脱FinalValue中的尾随空格: - )

SELECT * FROM @table_2

答案 2 :(得分:1)

基于变量的替换可以替换为表格。

DECLARE @Raw NVARCHAR(MAX) = '...';
SELECT @Raw= REPLACE(@Raw, P, R)
FROM (VALUES ('string-1', 'string_1'),
            ('string-2','string_2'),
            ('string-3','string_3'),
            ('string-4','string_4'),
) AS T(P, R);

要对表执行相同的逻辑,请考虑一些语句,如

SELECT col1, MultipleReplace(col1, replacement_table(P, R))
FROM some_table

因此,创建一个接受字符串输入和替换表的函数。为了将表传递给函数,我们必须创建一个表类型。

CREATE TYPE dbo.MulReplacements AS TABLE 
(
    Pattern NVARCHAR(MAX) NOT NULL,
    Replacement NVARCHAR(MAX) NOT NULL
)

然后函数将是

CREATE FUNCTION dbo.MulReplace(
    @string AS NVARCHAR(MAX),
    @replacements AS dbo.MulReplacements READONLY
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @result AS NVARCHAR(MAX) = @string;

    SELECT @result = REPLACE(@result, R.Pattern, R.Replacement) 
    FROM @replacements AS R;

    RETURN @result;
END

全部放在一起

DECLARE @replacement AS dbo.MulReplacements;

INSERT INTO @replacement
SELECT col1, REPLACE(col1, '-', '_')
FROM (VALUES ('string-1'), ('string-2'), ('string-3')) AS table_1(col1)

SELECT col1, dbo.Mulreplace(col1, @replacement)
FROM (VALUES ('text string-1 text string-3'), ('text string-3 string-2 t-ext'), ('string-2 text string-3 te-xt')) AS table_2(col1)

答案 3 :(得分:1)

使用动态查询执行此操作的一种方法。替换实际的表名和列名(注释在哪里更改)。

DECLARE @colNames VARCHAR(MAX) = ''
SELECT @colNames = @colNames + ', [' + table1_Col1 + ']' FROM tableName1 -- Table1 Column and Table1 Name
DECLARE @ReqColNames VARCHAR(MAX) = STUFF(@colNames, 1, 1, '')

DECLARE @int int
SELECT @int = count(*) FROM tableName1 -- Table1 Name
DECLARE @replace varchar(max) = replicate('REPLACE(', @int) + 't2.table2_Col2' -- Table2 Column

DECLARE @replaceCols varchar(max) = ''
SELECT @replaceCols = @replaceCols + ', r.[' + table1_Col1 + '], replace(r.[' + table1_Col1 + '], ''-'', ''_''))' FROM tableName1 -- Table1 Column and Table1 Name
DECLARE @ReplaceString varchar(max) = @replace + @replaceCols


DECLARE @cmd varchar(max) = 'SELECT ' +  @ReplaceString + ' FROM
(
    SELECT * FROM tableName1
    PIVOT
    (MAX (table1_Col1) FOR table1_Col1 IN (' + @ReqColNames + ')) x
) r
CROSS JOIN tableName2 t2'

EXEC(@cmd)
上面代码的

静态查询(以显示上述动态代码生成的内容):

Select replace(replace(replace(t2.table2_Col2
        , r.[string-1], replace(r.[string-1], '-', '_'))
        , r.[string-2], replace(r.[string-2], '-', '_'))
        , r.[string-3], replace(r.[string-3], '-', '_'))
from
(
    Select * from tableName1
    PIVOT
    (MAX (table1_Col1) FOR table1_Col1 IN ([string-1], [string-2], [string-3])) x
) r
CROSS JOIN tableName2 t2

输出:

text string_1 text string_3
text string_3 string_2 t-ext
string_2 text string_3 te-xt