我收到了客户的以下要求:
获取2013年从我们这里收到至少一个电子邮件广告系列的所有联系人的总帐户数。
其他信息:
问题:
我已经编写了一个能够返回正确结果的存储过程,但就性能而言,它的速度非常慢。代码需要遍历超过270,000个联系人,并在所有900个活动数据表中找到每个联系人的打开。它不知道当前正在检查的联系人存在哪个数据表,因此它还需要遍历所有的活动数据表来计算出来。由于广告系列统计信息存储在各个数据表中,因此我不知道如何避免使用循环来获取Opens。
联系人1 - >遍历所有数据表 - >获取联系人的总计开启1 联系人2 - >遍历所有数据表 - >为联系人2打开总计 ...... ... 接触N(N = 200,000) - >遍历所有数据表 - >为联系人N打开总计
以下是代码:
SELECT ROW_NUMBER() OVER (ORDER BY t.Email) As TempID, t.LeadID, t.Email, t.CampaignID, t.DataBaseName, t.DataTableName, 0 AS 'Opens', 0 AS 'Clicks'
INTO #temptb
FROM campaign_tracker t
INNER JOIN campaigns c ON c.CampaignID = t.CampaignID
WHERE t.DateAdded BETWEEN '2013-01-01 00:00:00.000' AND '2013-12-31 23:59:59.999' AND
c.CategoryID IN (1,2) AND t.Email IS NOT NULL
DECLARE @Sqlstr NVARCHAR(MAX)
DECLARE @outtb table (OutID INT, OutValue INT)
DECLARE @INTFlag INT, @Count INT, @Email VARCHAR(500), @DataBaseName VARCHAR(500), @DataTableName VARCHAR(500)
SET @INTFlag = 1
SET @Count = (SELECT COUNT(*) FROM #temptb)
WHILE (@INTFlag <= @Count)
BEGIN
SET @Email = (SELECT Email FROM #temptb WHERE TempID = @intFlag)
SET @DataBaseName = (SELECT DataBaseName FROM #temptb WHERE TempID = @intFlag)
SET @DataTableName = (SELECT DataTableName FROM #temptb WHERE TempID = @intFlag)
SET @Sqlstr = 'SELECT ' + CONVERT(VARCHAR,@INTFlag) + ', SUM(Opened) FROM ' + @DataBaseName + '.dbo.' + @DataTableName + ' WHERE Email = ''' + @Email + ''''
INSERT INTO @outtb (OutID, OutValue) EXEC (@Sqlstr)
SET @intFlag = @intFlag + 1
END
SELECT t.LeadID, t.Email, COUNT(t.Email) AS 'Total Emails Received', SUM(o.OutValue) AS 'Total Opens'
FROM #temptb t
LEFT OUTER JOIN @outtb o ON o.OutID = t.TempID
GROUP BY t.LeadID, t.Email
ORDER BY SUM(o.OutValue) DESC
以上将永远运行。有人可以就如何优化上述存储过程提出一些建议,以便我们可以在合理的时间范围内得到结果吗?非常感谢!