匹配最好的正则表达式
在下表中,我如何匹配'FG2-4G4T5
',以便第一个返回的行是最匹配的(这将是'FG2-4G
')?匹配最好的正则表达式
part_match
^FG2|^FF2|^FF3-S|^FF4-GR
^FG2-4G
^FG2
FG2-RGST
下面的查询不会在这种情况下工作,因为“^FG2|^FF2|^FF3-S|^FF4-GR
”具有更大的长度:
SELECT * FROM parts WHERE 'FG2-4G4T5' REGEXP part_match ORDER BY length(part_match) DEC
任何帮助将不胜感激。提前致谢。
假设你part_match的是一个总的形式^ XXXX和可选大小相等的^ YYYY |^ZZZZ | ...
SELECT * FROM parts
WHERE 'FG2-4G4T5' REGEXP part_match
ORDER BY instr(concat(part_match,'|'),'|') DEC
这会给你的最长前缀匹配。
为了解决FULL匹配的夹杂物,需要一断部分的匹配的长度,所以,
SELECT * FROM parts
WHERE 'FG2-4G4T5' REGEXP part_match
ORDER BY CASE WHEN part_match LIKE '^%' THEN -1 else 0 end +
instr(concat(part_match,'|'),'|') DEC
为了解决REGEX涉及不等长度,例如多段^YYYY|^Z|ABC
,你首先需要找到打破了为多行
part_match | single_part
^YYYY|^Z|ABC ^YYYY
^YYYY|^Z|ABC ^Z
^YYYY|^Z|ABC ABC
然后通过REGEXP引用single_part早在回答part_match的功能。这是不重要的,但可以通过Numbers表格和SUBSTR和INSTR的合理使用来实现。
创建一个数字表(运行此一次):
DROP PROCEDURE IF EXISTS CreateNumbersTable;
delimiter //
CREATE PROCEDURE CreateNumbersTable()
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
drop table if exists Numbers;
create table Numbers (N int primary key);
SET @x := 0;
REPEAT
insert into Numbers values (@x);
SET @x := @x + 1;
UNTIL @x > 999 END REPEAT;
END//
delimiter ;
CALL CreateNumbersTable;
DROP PROCEDURE CreateNumbersTable;
然后你可以使用此查询
select p.*
# ,substr(p.part_match, N.N+1, locate('|', concat(p.part_match,'|'), N.N+2) -N.N -1)
# ,length(substr(p.part_match, N.N+1, locate('|', concat(p.part_match,'|'), N.N+2) -N.N -1))
from parts p
inner join numbers N on N.N between 0 and length(p.part_match)
and ((N.N = 0) or (substr(p.part_match, N.N, 1) = '|'))
WHERE 'FG2-RGST' REGEXP p.part_match
and 'FG2-RGST' REGEXP substr(p.part_match, N.N+1, locate('|', concat(p.part_match,'|'), N.N+2) -N.N -1)
order by length(substr(p.part_match, N.N+1, locate('|', concat(p.part_match,'|'), N.N+2) -N.N -1)) DESC
取消注释行2和3,看part_match的它匹配的零件。
谢谢。也有完整的部分匹配(即'FG2-4G4T5'也可能在表格中) – 2011-03-08 20:22:16
它们的尺寸也不相同 – 2011-03-08 20:23:50
是的抱歉.....这是一张巨大的桌子,从一开始就设计得很糟糕。现在我知道公司发展很快;这现在是一个问题。我想避免使用C++来解决这个问题。 – 2011-03-08 20:34:19
有时K.I.S.S.解决方案最好。保留另一列,列出模式匹配的文本的实际长度?
part_match part_match_length
======================================
^FG2|^FF2|^FF3|^FF4 3
^FG2-4G 6
^FG2 3
,因此...
SELECT * FROM parts
WHERE 'FG2-4G4T5' REGEXP part_match
ORDER BY part_match_length DEC
技术上,第二列甚至没有到一定要长 - 只是某种给定模式如何很好的匹配提供指示。
Thanks.I can not have the thousands and millions millions of entries – 2011-03-08 20:21:21
如果你能以编程的方式确定长度(例如 - 选择每个模式,分割'|',并寻找最长的子字符串),那么你可以有一个脚本来为您创建专栏。仅仅因为它是一个单独的列,并不意味着你必须手动输入。 – Amber 2011-03-08 20:28:09
单个part_match可以包含多个长度,您需要确定“|||'的哪个组件是匹配的。此解决方案不起作用 – RichardTheKiwi 2011-03-08 20:36:34
哎呀,对不起@hsz吹你的编辑...我会放弃它。 – Donut 2011-03-08 19:37:40