遍历临时表以在SQL Server 2014中构建字符串的最佳方法

时间:2019-02-20 10:57:16

标签: sql sql-server

我创建了一个临时表,这个想法是我想遍历该表,用相同的电子邮件地址匹配所有记录,然后填充一个字符串,该字符串将进入电子邮件,然后删除该表。这将作为存储过程运行。

我使用的游标会先获取所有唯一的电子邮件地址,然后合并记录,但可能会有10万至50万条记录的性能,这是不可接受的,而且我知道必须有一种效率更高的方法

示例数据(不好意思,不知道如何正确格式化)

#temptable

temp_email, temp_string

test@test.com string1
test@test.com string2
test2@test.com string3
test2@test.com string4
test3@test.com string5

然后我要用此数据填充另一个表

emailto...   emailbody

test@test.com   'string1<br / > string2'
test2@test.com   'string3<br / > string4'
test3@test.com   'string5'

谢谢。

4 个答案:

答案 0 :(得分:4)

STUFFFOR XML PATH方法在SQl Server 2014及更早版本中可以很好地实现此目的。因为您有字符<>,所以之后需要“转义”它们:

WITH VTE AS(
    SELECT *
    FROM (VALUES('test@test.com','string1'),
                ('test@test.com','string2'),
                ('test2@test.com','string3'),
                ('test2@test.com','string4'),
                ('test3@test.com','string5')) V(Email, String))
SELECT Email,
       STUFF(REPLACE(REPLACE((SELECT '<br/>' + sq.String
                              FROM VTE sq
                              WHERE sq.Email = V.Email
                              FOR XML PATH('')),'&lt;','<'),'&gt;','>'),1,5,'')
FROM VTE V
GROUP BY Email;

答案 1 :(得分:1)

您不需要使用游标,请使用string_agg函数。

Create table #temptable 
(temp_email varchar(50), temp_string varchar(50))

INSERT INTO #temptable
VALUES ('test@test.com', 'string1'),
('test@test.com', 'string2'),
('test2@test.com', 'string3'),
('test2@test.com', 'string4'),
('test3@test.com', 'string5')


Select temp_email, STRING_AGG(temp_string,' <br/>')
from #temptable
Group by temp_email

答案 2 :(得分:0)

在SQL Server 2014中,有多种方法可以实现,而无需使用游标,但是从根本上讲,它们是相当复杂的hack,在我看来,这导致了非常难以理解的SQL。详细信息请参见此处:

How to concatenate text from multiple rows into a single text string in SQL server?

游标可以说是SQL 2014中最好的方法,因为至少它是可读的。

在Sql Server 2017中,有一个官方的聚合函数:

String_Agg

...但是那对你毫无用处。抱歉。

答案 3 :(得分:0)

您可以执行以下操作:

-- Create temp table
CREATE TABLE #temptable (temp_email varchar(50), temp_string varchar(50))

-- populate table with data
INSERT INTO #temptable
VALUES ('test@test.com', 'string1'),
('test@test.com', 'string2'),
('test2@test.com', 'string3'),
('test2@test.com', 'string4'),
('test3@test.com', 'string5')

-- actual query
    ;WITH CTE_table AS(
     SELECT C.temp_email,
      REPLACE(REPLACE(STUFF(
        (SELECT  CAST(temp_string AS VARCHAR(20))+'<br/>' AS [text()]
         FROM #temptable AS O
         WHERE C.temp_email= o.temp_email
         FOR XML PATH('')), 1, 0, NULL)
         ,'&lt;','<') -- replace this < with html code &lt;
         ,'&gt;','>') -- replace this > with html code &gt;
         AS temp_string
         ,ROW_NUMBER() OVER (partition by temp_email order by temp_email) rownumber
    FROM #temptable AS C
    ) 
    -- Get only unique records
    SELECT temp_email,temp_string FROM CTE_table 
    Where rownumber=1