简体   繁体   English

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

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

I have created a temp table, the idea being that I want to loop through it, match all records with the same email address and then populate a string, which will go in to an email, then drop the table. 我已经创建了一个临时表,这个想法是我想遍历该表,用相同的电子邮件地址匹配所有记录,然后填充一个字符串,该字符串将进入电子邮件,然后删除该表。 This will be run as a stored procedure. 这将作为存储过程运行。

I've used a cursor that first grabbed all the unique email addresses and then coalesce the records but with potentially 100k-500k records performance won't be acceptable, and I know there must be a far more efficient way of doing it. 我曾经使用过一个游标,该游标首先获取所有唯一的电子邮件地址,然后合并记录,但可能无法接受10万至50万条记录的性能,而且我知道必须有一种效率更高的方法。

Example data (apologies, don't know how to format it properly) 示例数据(抱歉,不知道如何正确格式化)

#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

I then want to populate another table with this data 然后,我想用此数据填充另一个表

emailto...   emailbody

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

Thank you. 谢谢。

The STUFF and FOR XML PATH method achieves this nicely in SQl Server 2014 and prior. STUFFFOR XML PATH方法可以在SQl Server 2014及更高版本中很好地实现此目的。 Because you have the characters < and > however, they need to be "un-escaped" afterwards: 因为您有字符<> ,但是之后需要将它们“转义”:

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;

you dont need to use cursor, please use string_agg function. 您不需要使用游标,请使用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

In SQL Server 2014 there are ways of doing this without a cursor but they are basically quite convoluted hacks and lead to pretty unreadable SQL in my opinion. 在SQL Server 2014中,有多种方法可以实现,而无需使用游标,但是从根本上讲,它们是相当复杂的hack,在我看来,这导致了非常难以理解的SQL。 See here for details: 详细信息请参见此处:

How to concatenate text from multiple rows into a single text string in SQL server? 如何在SQL Server中将多行文本合并为单个文本字符串?

A cursor is arguably the best way in SQL 2014 because at least its readable. 游标可以说是SQL 2014中最好的方式,因为至少它是可读的。

In Sql Server 2017 there is an official aggregation function for this: 在Sql Server 2017中,对此有一个官方的聚合函数:

String_Agg String_Agg

... but thats no use to you at the mo. ...但是那对你毫无用处。 Sorry. 抱歉。

You can do something like this : 您可以执行以下操作:

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