我要求在用户将实体保存到数据库之前生成可能重复的列表,并警告他们可能存在重复项。
有7个标准我们应该检查重复项,如果至少有3个匹配,我们应该将其标记给用户。 标准将全部与ID匹配,因此不需要模糊的字符串匹配,但我的问题来自这样一个事实:有很多可能的方法(如果我已经完成了我的总和,有99种方法)至少有3个项目可以匹配7种可能的清单。
我不想做99个单独的数据库查询来查找我的搜索结果,也不想从客户端的数据库和过滤器中恢复全部数据。我们目前可能只谈论成千上万的记录,但随着系统的成熟,这将增长到数百万。
任何人都有一个很好的有效方法来做到这一点? 我正在考虑一个简单的OR查询来获取记录,其中至少有一个字段与db匹配,然后在客户端上进行一些处理以对其进行更多过滤,但是一些字段具有非常低的基数并且实际上不会减少这个数字很大。
由于 乔恩
答案 0 :(得分:3)
OR
和CASE
求和将起作用但效率很低,因为它们不使用索引。
您需要使UNION
索引可用。
如果用户将name
,phone
,email
和address
输入数据库,您想要检查至少匹配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
这将使用这些字段上的索引,查询将很快。
有关详细信息,请参阅我的博客中的这篇文章:
3
4
个DISTINCT
条件匹配的记录另请参阅本文基于的question。
如果要在现有数据中包含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
匹配B
而C
匹配A
,则这并不意味着C
匹配{{1}}。
答案 1 :(得分: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
这未经过测试,但它显示了解决此问题的方法。
答案 2 :(得分:0)
你在使用什么DBS?有些人支持使用服务器端代码来使用这些约束。
答案 3 :(得分:0)
您是否考虑过使用带游标的存储过程?然后,您可以执行OR查询,然后逐个查找匹配的记录。使用存储过程可以让您对服务器进行所有检查。
但是,我认为包含数百万条记录的表扫描总是很慢。我认为你应该找出最有可能匹配的7个字段中的哪个是确保这些字段被编入索引。
答案 4 :(得分:0)
我假设您的系统正在尝试匹配某个帖子或类似内容的标签ID。这是一个多对多关系,您应该有三个表来处理它。一个用于帖子,一个用于标签,一个用于帖子和标签关系。
如果我的假设是正确的,那么处理此问题的最佳方法是:
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;