2011-03-08 107 views
1

在下表中,我如何匹配'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

哎呀,對不起@hsz吹你的編輯...我會放棄它。 – Donut 2011-03-08 19:37:40

回答

0

假設你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的它匹配的零件。

+0

謝謝。也有完整的部分匹配(即'FG2-4G4T5'也可能在表格中) – 2011-03-08 20:22:16

+0

它們的尺寸也不相同 – 2011-03-08 20:23:50

+0

是的抱歉.....這是一張巨大的桌子,從一開始就設計得很糟糕。現在我知道公司發展很快;這現在是一個問題。我想避免使用C++來解決這個問題。 – 2011-03-08 20:34:19

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 

技術上,第二列甚至沒有到一定要長 - 只是某種給定模式如何很好的匹配提供指示。

+0

Thanks.I can not have the thousands and millions millions of entries – 2011-03-08 20:21:21

+0

如果你能以編程的方式確定長度(例如 - 選擇每個模式,分割'|',並尋找最長的子字符串),那麼你可以有一個腳本來爲您創建專欄。僅僅因爲它是一個單獨的列,並不意味着你必須手動輸入。 – Amber 2011-03-08 20:28:09

+0

單個part_match可以包含多個長度,您需要確定「|||'的哪個組件是匹配的。此解決方案不起作用 – RichardTheKiwi 2011-03-08 20:36:34