MySQL查询匹配多种模式

时间:2019-01-18 00:16:37

标签: mysql

我试图找出一种解决方案,可以查询具有多种格式的字段的表,而我的输入格式也可能会有所不同。

我有一些表具有相同的PIN列(VARCHAR(20)),但是在每个表中,格式可能会有所不同,如下所示。通常,它是每个表的一种格式,但是您可以看到我可能遇到的所有不同变体。

PIN               |  ID
---------------------------
01-123.040-111-2  |  5
01-123.04-111     |  6
003.242424242.23  |  7
01.1234.345.22    |  8
1234456789        |  9

我希望能够接受以下输入中的任何以下变化:

> 012304041112
> 01.3456.342.22
> 02-3232323.2331

也许某些输入格式会完全匹配,有些则不会。所以这就是我的想法:

我正在使用PHP,因此我可以去除-和。或任何空格以获取原始数字,但是我不知道如何与该数字进行比较。表中的列。如果有一种方法可以将数字与仅数字进行比较,那将是最理想的选择。

例如:

input of 647382627 would match on 64.738.262-7 in the database

另一种情况可能是这样的输入:

  

12-25-9-123

应该匹配的地方:

12-25-009-123

[edit]为了澄清我的意思- 不同的县对包裹号使用不同的模式。一个县可能使用:

XX-XXXX-XXX-XX

表示其模式,但是在某些文档中,他们可能会说:

10-1234-5-2 where it translates to 10-1234-005-02

我们知道这适用于哪些县,但是输入的可能是

10123452 or 10-1234-005-02 or 10-1234-5-2

所以我不知道如何精确地进行比较。我猜想如果您要从输入和列中去除破折号和零,您可能会很接近,并且只需返回一些匹配项即可。

2 个答案:

答案 0 :(得分:2)

使用mysql,您可以使用正则表达式从字段中去除所有非数字字符,然后再进行比较,例如:

REGEXP_REPLACE(pin, '[^0-9]', '')
= REGEXP_REPLACE(?, '[^0-9]', '')

?是您输入的搜索内容。

正则表达式'[^0-9]'的意思是:01,...,9以外的任何字符。

这应该可以解决您对问题的最初描述,但是不会处理您给出的最后一个示例,其中'12-25-9-123'应该与'12-25-009-123'相匹配:为此,我们需要修改正则表达式。我建议附加规则应该是:立即禁止0开头的任何-

这是经过修改的正则表达式:

REGEXP_REPLACE(pin, '(-0+)|([^0-9])', '')

说明:

            EITHER
(-0+)         a dash followed by at least one 0
|           OR
([^0-9]+)   any non-numeric character

以下是您可以在this db fiddle中找到的示例:

 WITH mytable AS (
     SELECT '64.738.262-7' pin, '647382627' compare 
     UNION SELECT '12-25-9-123', '12-25-009-123'
     UNION SELECT 'abc', '12-25-009-123'
 )
 SELECT 
     pin,
     compare, 
    CASE 
        WHEN (REGEXP_REPLACE(pin, '(-0+)|([^0-9])', '') 
            = REGEXP_REPLACE(compare, '(-0+)|([^0-9])', ''))
        THEN 'match'
        ELSE 'no match'
    END result
 FROM mytable

 pin          | compare       | result
:----------- | :------------ | :------- 64.738.262-7 | 647382627 | match
12-25-9-123 | 12-25-009-123 | match
abc | 12-25-009-123 | no match

答案 1 :(得分:0)

(1)情境解决方案的想法

在MySQL表中创建一个生成的列,以仅存储pin列中的数字:

ALTER TABLE yourtable 
  ADD COLUMN pin_digits VARCHAR(20) 
  GENERATED ALWAYS AS (REGEXP_REPLACE(pin, '[^0-9]', '')) STORED;

然后在其上创建唯一索引以禁止重复:

ALTER TABLE yourtable ADD UNIQUE INDEX uq_idx_pin_digits (pin_digits);

现在(通过尝试插入)将您的输入与存储的数据进行比较时,您可以从该索引中受益:

INSERT INTO yourtable (pin) VALUES (REGEXP_REPLACE(?, '[^0-9]', '')); 
-- where ? is your input value passed from PHP (without any changes)
-- this will yield an error on unique constraint if the value already exists

实时演示

点击 here 查看其工作原理。