如何基于多行SQL查询结果按邮箱分组发送邮件(替代SSRS)
按邮箱分组汇总SQL数据并发送邮件的解决方案
优先方案:SQL层面预分组聚合
直接在SQL查询阶段把同一邮箱的多行数据合并为单条记录,后续发送逻辑和你已验证的单条数据场景完全一致,避免分组处理的麻烦。
适用于SQL Server 2017+(及兼容版本)
使用STRING_AGG函数拼接多行数据:
SELECT 姓名, 邮箱, -- 按需求拼接字段,CHAR(13)+CHAR(10)是换行符 STRING_AGG(CONCAT('订单号: ', 订单号, ', 金额: ', 金额), CHAR(13)+CHAR(10)) AS 用户数据汇总 FROM 你的业务表 GROUP BY 姓名, 邮箱
查询结果每个邮箱对应一行,直接循环发送即可。
适用于SQL Server旧版本(2016及更早)
用FOR XML PATH实现字符串拼接:
SELECT t.姓名, t.邮箱, STUFF(( SELECT CHAR(13)+CHAR(10)+'订单号: '+订单号+', 金额: '+金额 FROM 你的业务表 WHERE 邮箱 = t.邮箱 FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') AS 用户数据汇总 FROM 你的业务表 t GROUP BY t.姓名, t.邮箱
备选方案:脚本层面分组处理
如果无法修改SQL查询,可通过脚本读取全量数据后按邮箱分组再发送。
PowerShell示例
# 1. 读取SQL全量数据 $connStr = "Server=你的数据库服务器;Database=你的库名;Integrated Security=True;" $query = "SELECT 姓名, 邮箱, 订单号, 金额 FROM 你的业务表;" $dt = New-Object System.Data.DataTable $adapter = New-Object System.Data.SqlClient.SqlDataAdapter($query, $connStr) $adapter.Fill($dt) | Out-Null # 2. 按邮箱分组 $userGroups = $dt | Group-Object -Property 邮箱 # 3. 循环发送汇总邮件 foreach ($group in $userGroups) { $email = $group.Name $userName = $group.Group[0].姓名 $body = "您好 $userName,您的业务数据汇总如下:`n`n" foreach ($row in $group.Group) { $body += "订单号: $($row.订单号),金额: $($row.金额)`n" } # 发送邮件(需配置SMTP服务器) Send-MailMessage -To $email -From "业务通知<notify@yourdomain.com>" ` -Subject "你的专属业务数据汇总" -Body $body -SmtpServer "smtp.yourdomain.com" }
T-SQL游标方案(SQL Server内置邮件)
如果用SQL Server的Database Mail功能,可通过游标遍历分组用户并拼接内容:
DECLARE @姓名 NVARCHAR(50), @邮箱 NVARCHAR(100), @邮件内容 NVARCHAR(MAX) -- 定义游标遍历唯一用户 DECLARE user_cursor CURSOR FOR SELECT 姓名, 邮箱 FROM 你的业务表 GROUP BY 姓名, 邮箱 OPEN user_cursor FETCH NEXT FROM user_cursor INTO @姓名, @邮箱 WHILE @@FETCH_STATUS = 0 BEGIN -- 拼接该用户的所有数据 SET @邮件内容 = '您好 ' + @姓名 + ',您的业务数据汇总如下:' + CHAR(13)+CHAR(10)+CHAR(13)+CHAR(10) SELECT @邮件内容 = @邮件内容 + '订单号: ' + 订单号 + ',金额: ' + 金额 + CHAR(13)+CHAR(10) FROM 你的业务表 WHERE 邮箱 = @邮箱 -- 调用内置邮件发送存储过程 EXEC msdb.dbo.sp_send_dbmail @profile_name = '你的邮件配置文件名称', @recipients = @邮箱, @subject = '专属业务数据汇总', @body = @邮件内容 FETCH NEXT FROM user_cursor INTO @姓名, @邮箱 END CLOSE user_cursor DEALLOCATE user_cursor
方案选择建议
优先用SQL预分组的方式,数据库层面处理聚合效率更高,代码逻辑也更简洁;如果受限于SQL版本或权限,再考虑脚本或游标方案。
内容的提问来源于stack exchange,提问作者user19307825
相关产品推荐
相关产品推荐

