1

ユーザーがエンティティをデータベースに保存し、重複の可能性を警告する前に、可能性のある重複のリストを作成する必要があります。

重複をチェックする基準は 7 つあります。少なくとも 3 つ一致する場合は、ユーザーにフラグを立てる必要があります。基準はすべて ID で一致するため、あいまいな文字列の一致は必要ありませんが、少なくとも 3 つの項目が一致するために多くの可能な方法 (正確に合計を行った場合は 99 の方法) があるという事実に問題があります。 7つの可能性のリスト。

検索結果を見つけるために 99 の個別のデータベース クエリを実行する必要はありません。また、データベースからすべてを取得してクライアント側でフィルター処理する必要もありません。現時点ではおそらく数万のレコードしか話していませんが、システムが成熟するにつれて、これは数百万に成長するでしょう.

これを行うための効率的な方法を考えている人はいますか? データベースから少なくとも 1 つのフィールドが一致するレコードを取得する単純な OR クエリを検討し、クライアントで処理を行ってさらにフィルタリングしましたが、いくつかのフィールドはカーディナリティが非常に低く、実際には削減されません。膨大な量の数字。

ありがとうジョン

4

5 に答える 5

3

OR合計は機能しCASEますが、インデックスを使用しないため、非常に非効率的です。

UNIONインデックスを使用できるようにする必要があります。

ユーザーnameが 、phoneemailおよびをデータベースに入力し、これらのフィールドのaddress少なくとも 1 つに一致するすべてのレコードをチェックする場合は、次のコマンドを発行します。3

SELECT  i.*
FROM    (
        SELECT  id, COUNT(*)
        FROM    (
                SELECT  id
                FROM    t_info t
                WHERE   name  = 'Eve Chianese'
                UNION ALL
                SELECT  id
                FROM    t_info t
                WHERE   phone = '+15558000042'
                UNION ALL
                SELECT  id
                FROM    t_info t
                WHERE   email = '42@example.com'
                UNION ALL
                SELECT  id
                FROM    t_info t
                WHERE   address = '42 North Lane'
                ) q
        GROUP BY
                id
        HAVING  COUNT(*) >= 3
        ) dq
JOIN    t_info i
ON      i.id = dq.id

これにより、これらのフィールドでインデックスが使用され、クエリが高速になります。

詳細については、私のブログのこの記事を参照してください。

この記事の基になっているこの質問も参照してください。

DISTINCT既存のデータに値のリストが必要な場合は、このクエリをサブクエリにラップするだけです。

SELECT  i.*
FROM    t_info i1
WHERE   EXISTS
        (
        SELECT  1
        FROM    (
                SELECT  id
                FROM    t_info t
                WHERE   name  = i1.name
                UNION ALL
                SELECT  id
                FROM    t_info t
                WHERE   phone = i1.phone
                UNION ALL
                SELECT  id
                FROM    t_info t
                WHERE   email = i1.email
                UNION ALL
                SELECT  id
                FROM    t_info t
                WHERE   address = i1.address
                ) q
        GROUP BY
                id
        HAVING  COUNT(*) >= 3
        )

これDISTINCTは推移的ではないAことBに注意してください。BCAC

于 2009-05-05T16:14:55.727 に答える
2

次のようなものが必要になる場合があります。

SELECT id
FROM 
    (select id, CASE fld1 WHEN input1 THEN 1 ELSE 0 "rule1",
        CASE fld2 when input2 THEN 1 ELSE 0 "rule2",
        ...,
        CASE fld7 when input7 THEN 1 ELSE 0 "rule2",
    FROM table)
WHERE rule1+rule2+rule3+...+rule4 >= 3

これはテストされていませんが、これに取り組む方法を示しています。

于 2009-05-05T16:23:05.987 に答える
0

どのDBSを使用していますか? サーバー側のコードを使用して、このような制約の使用をサポートするものもあります。

于 2009-05-05T16:15:49.220 に答える
0

カーソルでストアド プロシージャを使用することを検討しましたか? 次に、OR クエリを実行してから、レコードを 1 つずつ検索して一致を探すことができます。ストアド プロシージャを使用すると、サーバー上ですべてのチェックを行うことができます。

ただし、何百万ものレコードを含むテーブル スキャンは常に遅くなると思います。7 つのフィールドのうちどれが一致する可能性が最も高いかを調べて、これらがインデックス化されていることを確認する必要があると思います。

于 2009-05-05T16:17:59.963 に答える
0

あなたのシステムは、特定の投稿のタグ ID などと一致させようとしていると思います。これは多対多の関係であり、それを処理するには 3 つのテーブルが必要です。1 つは投稿用、1 つはタグ用、もう 1 つは投稿とタグの関係用です。

私の仮定が正しい場合、これを処理する最良の方法は次のとおりです。

SELECT postid, count(tagid) as common_tag_count
FROM posts_to_tags
WHERE tagid IN (tag1, tag2, tag3, ...)
GROUP BY postid
HAVING count(tagid) > 3;
于 2009-05-05T16:19:32.797 に答える