【发布时间】:2011-07-05 09:04:09
【问题描述】:
我有一个带有代码的表格和另一个带有前缀的表格。我需要匹配每个代码的(最长)前缀。
还有一个次要范围,我必须在其中限制前缀(这涉及引入其他表)。我认为在大多数情况下这并不重要,但这是一个简化(规范化)的方案(我必须设置 item.prefix_id):
group (id)
subgroup (id, group_id)
prefix (id, subgroup_id, prefix)
item (id, group_id, code, prefix_id)
可以将前缀的长度缓存在一个新的字段中并对其进行索引。可以将 group_id 缓存在前缀表中(尽管组是相当小的表,但在大多数情况下,我认为不会获得任何性能提升)。 item表包含几十万条记录,前缀最多包含500条。
编辑:
对不起,如果问题没有得到足够的定义。当使用“前缀”这个词时,我的意思是它,所以代码必须以实际前缀开始。
subgroup
id group_id
-------------
1 1
2 1
3 1
4 2
prefix
id subgroup_id prefix
------------------------
1 1 a
2 2 abc
3 2 123
4 4 abcdef
item
id group_id code prefix_id
-----------------------------------
1 1 abc123 NULL
2 1 abcdef NULL
3 1 a123 NULL
4 2 abc123 NULL
前缀列的预期结果是(item.id, item.prefix_id):
(1, 2) 因为:子组 1、2、3 在组 1 下,代码 abc123 以前缀 a 开头,前缀 abc 和 abc 是两者中的 logest , 所以我们把abc 的id 2 放入item.prefix_id.
(2, 2) 因为:尽管前缀 {4}(即abcdef)是最匹配的前缀,但它的子组(即 4)在组 2 下但项目在组 1 下,所以我们可以从子组 1、2、3 中进行选择,而 abc 仍然是三个可能前缀中的对数匹配。
(3, 1) 因为:a 是最匹配的。
(4, NULL) 因为:第 4 项在组 2 下,组 2 下的唯一前缀是 abcdef,与 abc123 不匹配(因为 abc123 不以 abcdef 开头)。
但正如我所说,整个摸索的事情不是问题的重要部分。我主要关心的是将带有可能前缀的表与字符串表相匹配,以及如何以 best 的方式进行匹配。 (最好的意思是可读性、可维护性和性能之间的最佳权衡——因此是标题中的“最佳实践”)。
目前我正在做类似的事情:
UPDATE item USE INDEX (code3)
LEFT JOIN prefix ON prefix.length=3 AND LEFT(item.code,3)=prefix.prefix
LEFT JOIN subgroup ON subgroup.id=prefix.subgroup_id
WHERE subgroup.group_id == item.group_id AND
item.segment_id IS NULL
其中code3 是KEY code3 (segment_id, group_id, code(3))。 - 以 1、2、3 和 4 为长度重复相同的逻辑。它看起来非常有效,但我不喜欢其中存在重复(单个操作有 4 个查询)。 - 当然,这是在前缀的最大长度为 4 的情况下。
感谢大家到目前为止分享你的想法。
【问题讨论】:
-
到目前为止您尝试过哪些查询?
-
两个长度相同的前缀怎么办?
-
@vbence
code的列类型是什么?如果是 varchar,那么 varchar 的长度是多少?还有关于前缀的同样问题。 -
系统中有两个地方用到了这个逻辑。在一种情况下,它最多为 8 个字符,另一种情况下,它的固定长度为 4。它们是存储在 VARCHAR 字段中的字母数字。没有相同的前缀,因此每个长度最多有一个匹配项。
标签: mysql