繁体   English   中英

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

[英]Best way to Iterate through temp table to build string in SQL Server 2014

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

我曾经使用过一个游标,该游标首先获取所有唯一的电子邮件地址,然后合并记录,但可能无法接受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'

谢谢。

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;

您不需要使用游标,请使用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

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

如何在SQL Server中将多行文本合并为单个文本字符串?

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

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

String_Agg

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

您可以执行以下操作:

-- 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 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM