0

我正在开发一个社交网络 Web 应用程序,我遇到了需要向尚未激活电子邮件的用户重新发送提醒电子邮件的情况。

问题是当我调查数据库时,我发现许多电子邮件是重复的(显然没有对电子邮件唯一性进行验证。所以我需要知道的是从数据库中检索这些字段的用户名、电子邮件激活码、电子邮件、这样我就可以重新发送激活电子邮件,对于重复的电子邮件,我只需要返回其中一个(即,如果我的用户 john 的电子邮件为 john@hotmail.com 和用户 john1 的电子邮件为 john@hotmail.com ,我只想检索这些 johns 中的一个,无论 john1 还是两个),所以我想通过(Group By Email)跟踪 SQL 查询。

问题是我无法选择不在 group by 子句中的其他字段。我在这里的解决方案是我不喜欢的;我创建了一个列表,每次需要向用户发送电子邮件时,我都会遍历整个列表以确保该电子邮件不存在,如果不存在,我发送给它,然后将电子邮件添加到列表。
类似于以下内容:

if(!EmailIsInList(email)){ 
  SendActivationEmail(email);
  AddEmailToList(email)
}
else { DoNotSend); }

实际上,我以这种方式解决了问题,但我仍然不喜欢我的解决方案。有任何想法吗?

4

3 回答 3

1

收入测试数据:

DECLARE @User TABLE (UserId int, 
UserName varchar(100), Email varchar(40), IsActivated bit)
INSERT INTO @User
SELECT 1, 'John', 'john@hotmail.com', 0 UNION
SELECT 2, 'Ann', 'ann@hotmail.com', 0 UNION
SELECT 3, 'John2', 'john@hotmail.com', 1 UNION
SELECT 4, 'Bill', 'bill@hotmail.com', 0 UNION
SELECT 5, 'Bill', 'john@hotmail.com', 0

DECLARE @Email TABLE (EmailId int, 
UserId int, Date datetime, Message varchar(1000))
INSERT INTO @Email
SELECT 1, 1, GETDATE(), '' UNION
SELECT 2, 2, GETDATE(), '' UNION
SELECT 3, 3, GETDATE(), '' UNION
SELECT 4, 4, GETDATE(), '' UNION
SELECT 5, 5, GETDATE(), ''

SELECT * FROM @User
SELECT * FROM @Email

你看,我们已经激活了一次 john@hotmail.com,所以我们不需要他在结果集中。
现在,使用 RANK OVER 实现:

SELECT M.UserID, M.UserName, M.Email, 
    M.IsActivated, M.EmailId, M.Date, M.Message 
FROM (
    SELECT RANK() OVER (PARTITION BY U.Email 
        ORDER BY U.IsActivated Desc, U.UserID ASC) AS N, 
        U.UserID, U.UserName, U.Email, U.IsActivated, 
        E.EmailId, E.Date, E.Message
    FROM @User U INNER JOIN @Email E ON U.UserID = E.UserID
)M WHERE M.N = 1 AND M.IsActivated = 0
于 2009-02-25T13:56:32.830 回答
0

如果我们假设同一个电子邮件地址既可以针对 usera 激​​活,也可以针对 userb 不激活,那么以下查询将为您返回一个从未激活过的电子邮件地址的用户 ID

SELECT  MAX(userid),
        email
FROM    users AS u1
WHERE   activated = 'False'
AND NOT EXISTS (
        SELECT 1
        FROM   users AS u2
        WHERE  u2.email = u1.email
        AND    u2.activated = 'True'
        )

GROUP BY email

您确实希望确保对电子邮件字段进行索引,并且如果使用 (email, userid) 的唯一复合键对其进行索引,那么这将是索引扫描,并且应该非常快。

于 2009-02-25T12:53:04.417 回答
0

我认为你犯了一个重大的逻辑错误。电子邮件地址不是,也永远不会是唯一的。仅仅因为两个用户拥有相同的电子邮件地址并不意味着他们是同一个人!人们经常共享电子邮件,夫妻可能拥有相同的电子邮件,小型办公室有时只有一封电子邮件(这通常适用于医生办公室。)如果有人放弃,电子邮件也会被重复使用。因此,2007 年在 jsmith@hotmail.com 注册的 John Smith 在您的系统中可能还没有处于活动状态,因此当他访问 jsmith@gmail.com 时也没有费心去更改他的电子邮件。与此同时,Judy Smith 在不同的州注册 jsmith@hotmail.com。您不能假设电子邮件地址永远是唯一的。

于 2009-02-25T14:45:45.347 回答