0

私はソーシャル ネットワークの Web アプリケーションに取り組んでおり、メールを有効にしていないユーザーにリマインダー メールを再送信する必要がある状況に陥りました。

問題は、DB を調査したところ、多くの電子メールが重複していることがわかりました (明らかに電子メールの一意性に関する検証が行われていませんでした。そのため、知っておく必要があるのは、DB からこれらのフィールド、ユーザー名、電子メール アクティベーション コード、電子メールを取得することです。アクティベーションメールを再送信できるように、メールが重複している場合は、そのうちの 1 つだけを返す必要があります (つまり、john@hotmail.com というメールアドレスを持つユーザー john と john@hotmail.com というメールアドレスを持つユーザー john1 がいる場合) 、john1または2に関係なく、これらのjohnの1つだけを取得したいので、(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

あなたは大きな論理的誤りを犯していると思います。電子メールアドレスは一意ではなく、一意になることはありません。2人のユーザーが同じメールアドレスを持っているからといって、彼らが同じ人であるとは限りません。人々はしばしば電子メールを共有し、カップルは同じ電子メールを持っているかもしれません、小さなオフィスは時々1つの電子メールしか持っていません(これはしばしば医者のオフィスに当てはまります)。したがって、2007年にjsmith@hotmail.comに登録したJohn Smithは、システムでまだアクティブになっていない可能性があるため、jsmith@gmail.comにアクセスしたときにわざわざメールを変更しませんでした。その間、異なる状態のJudySmithはjsmith@hotmail.comを登録します。メールアドレスが一意であると想定することはできません。

于 2009-02-25T14:45:45.347 に答える
0

同じ電子メール アドレスが usera に対してアクティブ化され、userb に対してアクティブ化されない可能性があると仮定すると、次のクエリは、アクティブ化されていない各電子メール アドレスに対して 1 つのユーザー 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

メール フィールドがインデックス化されていることを確認する必要があります。(メール、ユーザー ID) の一意の複合キーでインデックス化されている場合、これはインデックス付きスキャンであり、非常に高速です。

于 2009-02-25T12:53:04.417 に答える