在下表中,我如何匹配“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
任何帮助将不胜感激。提前谢谢。
答案 0 :(得分:2)
有时是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
从技术上讲,第二列甚至不一定必须是长度 - 只是指示给定模式提供的匹配有多好。
答案 1 :(得分:0)
假设你的part_match总是^ xxxx形式,并且可选择EQUAL-SIZED ^ 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
然后通过single_part的REGEXP引用回答中的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部分。