Mar*_*son 11 sql sql-server-2008
我试图想象我如何使用另一个表中的数据替换字符串
我有一个看起来像这样的表:
Id Translation 1 Peter 2 Sandra 3 Olga
现在我想选择all并使用如下所示的列表替换翻译:
Original New e # r ? lg *%
这样选择列表如下所示:
Id Translation 1 P#t#? 2 Sand?a 3 O*%a
因此,对于每个翻译,我需要有一个REPLACE(翻译,原创,新).换句话说:我需要在我的第一个列表中查看每个"翻译"并在替换表中再次循环以查看要替换的内容
请记住,第一个列表有25'000行,第二个列表有50'000,所以我不能手工输入:)
只是为了澄清:我的查找表中的Original和New可以是字母和单词,所以表格看起来像这样:
Original New one two three fifty sun moon
要在一个查询中执行此操作,您需要使用递归CTE.就像是:
with trans as (
select t.original, t.new, row_number() over (order by t.original) as seqnum,
count(*) over () as cnt
from translations
),
t as (
select tt.id, tt.string, replace(tt.string, trans.original, trans.new) as replaced,
seqnum + 1 as seqnum, cnt
from totranslate tt join
trans
on trans.id = 1
union all
select t.id, t.string, replace(t.string, trans.original, trans.new),
seqnum + 1 as seqnum, cnt
from t join
trans
on t.seqnum = trans.id
where t.seqnum <= t.cnt
)
select t.id, t.string, t.replaced
from t
where seqnum = cnt;
Run Code Online (Sandbox Code Playgroud)
还有递归cte:
DECLARE @translations TABLE
(
Id INT ,
Translation NVARCHAR(20)
)
INSERT INTO @translations
VALUES ( 1, 'Peter' ),
( 2, 'Sandra' ),
( 3, 'Olga' )
DECLARE @replacements TABLE
(
Original VARCHAR(2) ,
New VARCHAR(2)
)
INSERT INTO @replacements
VALUES ( 'e', '#' ),
( 'r', '?' ),
( 'lg', '*%' );
WITH cte1 AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY (SELECT 1)) rn
FROM @translations CROSS JOIN @replacements),
cte2 AS (SELECT Id, rn, REPLACE(Translation, Original, New) AS NTranslation
FROM cte1
WHERE rn = 1
UNION ALL
SELECT c2.Id, c2.rn + 1, REPLACE(c2.NTranslation, c1.Original, c1.New)
FROM cte1 c1
JOIN cte2 c2 ON c2.Id = c1.Id AND c2.rn + 1 = c1.rn)
SELECT * FROM cte2
WHERE rn = (SELECT COUNT(*) FROM @replacements)
ORDER BY Id
Run Code Online (Sandbox Code Playgroud)
编辑:
WITH cte1 AS (SELECT t.*, p.Id AS Old, p.Code, ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY (SELECT 1)) rn
FROM translations t CROSS JOIN Property p),
cte2 AS (SELECT Id, rn, REPLACE(Trans, Old, Code) AS NTranslation
FROM cte1
WHERE rn = 1
UNION ALL
SELECT c2.Id, c2.rn + 1, REPLACE(c2.NTranslation, c1.Old, c1.Code)
FROM cte1 c1
JOIN cte2 c2 ON c2.Id = c1.Id AND c2.rn + 1 = c1.rn)
SELECT * FROM cte2
WHERE rn = (SELECT COUNT(*) FROM Property)
ORDER BY Id
Run Code Online (Sandbox Code Playgroud)
您可以使用UDF:
CREATE FUNCTION [dbo].[Translate]
(
-- Add the parameters for the function here
@Str nvarchar(max)
)
RETURNS nvarchar(max)
AS
BEGIN
DECLARE @Result nvarchar(max) = @Str;
SELECT @Result = replace(@Result,Original,New) from dbo.Mappings order BY Pos;
RETURN @Result;
END
Run Code Online (Sandbox Code Playgroud)
在这里,我假设调用包含翻译的表,dbo.Mappings并且在列Original和New列旁边需要另一列Pos int,用于确定应用翻译的顺序(以解决@Thorsten Kettner在评论中提到的问题)