Sql server SQLServer:使用其他表中的数据分组并替换列值,而不使用UDF

Sql server SQLServer:使用其他表中的数据分组并替换列值,而不使用UDF,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我想用@ModTable table中的等效文本替换@CommentsTable列“Comments”中的数字,而无需在单个SELECT中使用UDF。可以用CTE。尝试了替换的东西,但没有运气 任何建议都会有很大帮助 样本: DECLARE @ModTable TABLE ( ID INT, ModName VARCHAR(10), ModPos VARCHAR(10) ) DECLARE @CommentsTable TABLE ( ID I

我想用@ModTable table中的等效文本替换@CommentsTable列“Comments”中的数字,而无需在单个SELECT中使用UDF。可以用CTE。尝试了替换的东西,但没有运气

任何建议都会有很大帮助

样本:

DECLARE @ModTable TABLE
(  
    ID INT,  
    ModName VARCHAR(10),  
    ModPos VARCHAR(10) 
)

DECLARE @CommentsTable TABLE
(  
    ID INT,  
    Comments VARCHAR(100)
)

INSERT INTO @CommentsTable  
VALUES  (1, 'MyFirst 5 Comments with 6'),
        (2, 'MySecond comments'),
        (3, 'MyThird comments 5')

INSERT INTO @ModTABLE  
VALUES  (1, '[FIVE]', '5'),
        (1, '[SIX]', '6'),
        (1, '[ONE]', '1'),
        (1, '[TWO]', '2')

SELECT T1.ID, <<REPLACED COMMENTS>>     
FROM @CommentsTable T1  
GROUP BY T1.ID, T1.Comments


**Expected Result:**
ID Comments               
1  MyFirst [FIVE] Comments with [SIX]
2  MySecond comments
3  MyThird comments [FIVE]
DECLARE@ModTable表
(  
ID INT,
ModName VARCHAR(10),
ModPos VARCHAR(10)
)
声明@CommentsTable表
(  
ID INT,
瓦查尔评论(100)
)
插入@CommentsTable
值(1,‘我的前5条注释加6’),
(2,“我的第二条评论”),
(3,‘MyThird评论5’)
插入@ModTABLE
值(1、[5]、“5”),
(一"六","六",,
(一),"一",,
(一,"两","二")
选择T1.ID,
从@T1开始
按T1.ID、T1.Comments分组
**预期结果:**
ID注释
1我的第一个[五个]评论加上[六个]
2我的第二条评论
3 MyThird评论[五]

创建一个光标,跨越
@ModTable
并每次进行一次替换

DECLARE replcursor FOR SELECT ModPos, ModName FROM @ModTable;
OPEN replcursor;

DECLARE modpos varchar(100) DEFAULT "";
DECLARE modname varchar(100) DEFAULT "";

get_loop: LOOP
    FETCH replcursor INTO @modpos, @modname

    SELECT T1.ID, REPLACE(T1.Comments, @modpos, @modname)     
    FROM @CommentsTable T1  
    GROUP BY T1.ID, T1.Comments
END LOOP get_loop;

当然,您可以将结果存储在临时表中,并在循环结束时获得所有结果

创建一个光标,跨越
@ModTable
并每次进行一次替换

DECLARE replcursor FOR SELECT ModPos, ModName FROM @ModTable;
OPEN replcursor;

DECLARE modpos varchar(100) DEFAULT "";
DECLARE modname varchar(100) DEFAULT "";

get_loop: LOOP
    FETCH replcursor INTO @modpos, @modname

    SELECT T1.ID, REPLACE(T1.Comments, @modpos, @modname)     
    FROM @CommentsTable T1  
    GROUP BY T1.ID, T1.Comments
END LOOP get_loop;

当然,您可以将结果存储在临时表中,并在循环结束时获得所有结果

您可以使用while循环来迭代记录和mod。我稍微修改了@ModTable,使其ID具有唯一值。如果这不是您的数据结构,那么您可以使用诸如ROW_NUMBER()之类的窗口函数来获取唯一值,您可以在该值上进行迭代

修订脚本示例:

  DECLARE @ModTable TABLE
 (  
    ID INT,  
    ModName VARCHAR(10),  
    ModPos VARCHAR(10) 
  )

   DECLARE @CommentsTable TABLE
(  
    ID INT,  
    Comments VARCHAR(100)
)


   INSERT INTO @CommentsTable  
VALUES  (1, 'MyFirst 5 Comments with 6'),
        (2, 'MySecond comments'),
        (3, 'MyThird comments 5')

   INSERT INTO @ModTABLE  
VALUES  (1, '[FIVE]', '5'),
        (2, '[SIX]', '6'),
        (3, '[ONE]', '1'),
        (4, '[TWO]', '2')


declare @revisedTable table (id int, comments varchar(100))
declare @modcount int = (select count(*) from @ModTable)
declare @commentcount int = (select count(*) from @CommentsTable)
declare @currentcomment varchar(100) = ''
while @commentcount > 0
    begin
        set @modcount = (select count(*) from @ModTable)
        set @currentcomment = (select Comments from @CommentsTable where ID = @commentcount)
        while @modcount > 0
            begin
                set @currentcomment = REPLACE(  @currentcomment, 
                                                (SELECT TOP 1 ModPos FROM @ModTable WHERE ID = @modcount), 
                                                (SELECT TOP 1 ModName FROM @ModTable WHERE ID = @modcount))
                set @modcount = @modcount - 1
            end
        INSERT INTO @revisedTable (id, comments) 
        SELECT @commentcount, @currentcomment
        set @commentcount = @commentcount - 1
    end

SELECT *
FROM @revisedTable
order by id

您可以使用while循环来迭代记录和mod。我稍微修改了@ModTable,使其ID具有唯一值。如果这不是您的数据结构,那么您可以使用诸如ROW_NUMBER()之类的窗口函数来获取唯一值,您可以在该值上进行迭代

修订脚本示例:

  DECLARE @ModTable TABLE
 (  
    ID INT,  
    ModName VARCHAR(10),  
    ModPos VARCHAR(10) 
  )

   DECLARE @CommentsTable TABLE
(  
    ID INT,  
    Comments VARCHAR(100)
)


   INSERT INTO @CommentsTable  
VALUES  (1, 'MyFirst 5 Comments with 6'),
        (2, 'MySecond comments'),
        (3, 'MyThird comments 5')

   INSERT INTO @ModTABLE  
VALUES  (1, '[FIVE]', '5'),
        (2, '[SIX]', '6'),
        (3, '[ONE]', '1'),
        (4, '[TWO]', '2')


declare @revisedTable table (id int, comments varchar(100))
declare @modcount int = (select count(*) from @ModTable)
declare @commentcount int = (select count(*) from @CommentsTable)
declare @currentcomment varchar(100) = ''
while @commentcount > 0
    begin
        set @modcount = (select count(*) from @ModTable)
        set @currentcomment = (select Comments from @CommentsTable where ID = @commentcount)
        while @modcount > 0
            begin
                set @currentcomment = REPLACE(  @currentcomment, 
                                                (SELECT TOP 1 ModPos FROM @ModTable WHERE ID = @modcount), 
                                                (SELECT TOP 1 ModName FROM @ModTable WHERE ID = @modcount))
                set @modcount = @modcount - 1
            end
        INSERT INTO @revisedTable (id, comments) 
        SELECT @commentcount, @currentcomment
        set @commentcount = @commentcount - 1
    end

SELECT *
FROM @revisedTable
order by id

尽管我通常避免递归查询,但我认为这种方法仍然有效。它假定您有连续的ID,但:

with Comments as
( 
    select ID, Comments, 0 as ConnectID
    from @CommentsTable
    union all
    select ID, replace(c.Comments, m.ModPos, m.ModName), m.ConnectID
    from Comments c inner join @ModTable m on m.ConnectID = c.ConnectID + 1
) 
select * from Comments
where ConnectID = (select max(ID) from @ModTable)

尽管我通常避免递归查询,但我认为这种方法仍然有效。它假定您有连续的ID,但:

with Comments as
( 
    select ID, Comments, 0 as ConnectID
    from @CommentsTable
    union all
    select ID, replace(c.Comments, m.ModPos, m.ModName), m.ConnectID
    from Comments c inner join @ModTable m on m.ConnectID = c.ConnectID + 1
) 
select * from Comments
where ConnectID = (select max(ID) from @ModTable)
=>CLR函数()

由于我在“CommentsTable”中有很多记录,“ModTable”中的每个注释都有多个ModName,所以最终决定使用CLR函数。谢谢大家的建议和指点。

=>CLR函数()


由于我在“CommentsTable”中有很多记录,“ModTable”中的每个注释都有多个ModName,所以最终决定使用CLR函数。谢谢大家的建议和指点。

表值函数和标量都是不可能的?在操作之前插入一些临时表是否可以?您的替换可能会对应用程序的顺序敏感。“当一个数字变成两位数时会发生什么?”游戏是肯定的。请尝试使用临时表的解决方案。@shawnt00供参考,幸运的是,我现在的范围是1…9。表值函数和标量都是不可能的?在操作之前插入一些临时表可以吗?您的替换可能对应用程序的顺序很敏感。“当一个数字变成两位数时会发生什么?”游戏是肯定的。请使用临时表尝试您的解决方案。@shawnt00仅供参考,幸运的是,我现在只有1…9的范围。谢谢您的回复。希望WHILE比Omar Alves的游标实现更好!?我自己工作。。。。并将等待更多的建议。请容忍我。谢谢你的回复。希望WHILE比Omar Alves的游标实现更好!?我自己工作。。。。并将等待更多的建议。请容忍我。