SQL替换列表

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

Gor*_*off 8

要在一个查询中执行此操作,您需要使用递归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)


Gio*_*uri 5

还有递归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)


B0A*_*rew 5

您可以使用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并且在列OriginalNew列旁边需要另一列Pos int,用于确定应用翻译的顺序(以解决@Thorsten Kettner在评论中提到的问题)

  • @MarcusOhlsson,如果你不是专家,为什么不首先尝试拒绝这个想法呢? (2认同)