我创建了一个临时表,这个想法是我想遍历该表,用相同的电子邮件地址匹配所有记录,然后填充一个字符串,该字符串将进入电子邮件,然后删除该表。这将作为存储过程运行。
我使用的游标会先获取所有唯一的电子邮件地址,然后合并记录,但可能会有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'
谢谢。
答案 0 :(得分:4)
STUFF
和FOR 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('')),'<','<'),'>','>'),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中,有一个官方的聚合函数:
...但是那对你毫无用处。抱歉。
答案 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)
,'<','<') -- replace this < with html code <
,'>','>') -- replace this > with html code >
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