TSQL:在一个查询中多次替换相同的字段 [英] TSQL: Replace same field multiple times in one query

查看:28
本文介绍了TSQL:在一个查询中多次替换相同的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个替换表,是否可以将所有替换应用于同一个查询中的表中的列?

Given a table of replacements, can all the replacements be applied to a column in a table in the same query?

免责声明:我可以使用游标或动态 sql 来创建嵌套的替换字符串;我想知道是否可以简明扼要地完成.

Disclaimer: I can do this with a cursor, or with dynamic sql to create a nested string of replacements; I want to know if it could be done concisely.

我有一个替换表,

create table #replacements(old varchar(max), new varchar(max))
insert into #replacements values
('X','Y'),
('A','B'),
('W','V'),
('C','D')

和要替换的值表:

create table #value(value varchar(max))
insert into #value values
('XA'),
('WC')

我想在一个返回的查询中执行这些:

I'd like to perform these in one query which gives back:

YB

VD

有没有办法做到这一点?我试过了,

Is there any way to do this? I tried,

update v
set value = replace(value,old,new)
from #value v,
#replacements

但这给出了(只完成了完整连接中的第一行):

but this gives (only the first row in the full join is done):

是的

厕所

推荐答案

JBond 的回答很简单,但是对于任何大量的行来说它都很慢,因为它将是 RBAR.他的函数必须一个一个地获取每个值,然后在你的替换表中运行它.对于大量行,您会看到一些严重的性能问题.

JBond's answer is simple but it's SLOW for any large number of rows since it will be RBAR. His function has to grab each value one by one and then run it through your replacement table. With a large number of rows, you'll see some serious performance issues.

这是一个动态查询,在我看来,它比 Vasily 的简单一点,尽管两者实际上做的是相同的事情.代码对于任意数量的行都应该表现得非常好.试试看:

Here's a dynamic query that is, in my opinion, a little simpler than Vasily's, although both really do the same thing. The code should perform really well for any number of rows. Try it out:

DECLARE @Replace VARCHAR(MAX);

SELECT @Replace = COALESCE('REPLACE(' + @Replace,'REPLACE(value') + ',''' + old + ''',''' + new + ''')'
FROM #replacements


EXEC
(
    'UPDATE #value
    SET Value = ' + @Replace
)

递归解决方案

WITH CTE_replacements
AS
(
    SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) row_num,
            old,
            new
    FROM #replacements
),
CTE_recursion
AS
(
    SELECT  REPLACE(value,old,new) AS value,
            1 AS cnt
    FROM #value
    CROSS APPLY (SELECT old,new FROM CTE_replacements WHERE row_num = 1) CA

    UNION ALL

    SELECT  REPLACE(value,old,new) AS value,
            cnt + 1
    FROM cte_recursion A
    CROSS APPLY (SELECT old,new FROM CTE_replacements WHERE row_num = cnt + 1) CA

)

SELECT TOP(SELECT COUNT(*) FROM #value) *
FROM CTE_recursion
ORDER BY 2 DESC
OPTION (MAXRECURSION 0)

与动态SQL方案相比,这不是很好.相比于功能,它更好.递归的作用是将每个更改一一应用于整个数据集.所以替换行应用于所有数据.然后将第二个更改(行)应用于整个数据集等...因此对于少量更改,因为它通过了 RBAR,然后设置了一个不太大的值,它将起作用正好.

Compared to the dynamic SQL solution, this is not great. Compared to the function, it is better. What the recursion does is apply each change one by one to the entire dataset. So the row in replacement is applied to all the data. Then the second change(row) is applied to the entire dataset etc... So for a small number of changes because it goes through it RBAR, and then a not too large value set, it will work just fine.

这篇关于TSQL:在一个查询中多次替换相同的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆