MySQL REGEXP的行为不符合预期

时间:2014-07-06 00:03:02

标签: mysql regex

我的问题是regexp在不同的上下文中给出相同的模式似乎没有给出相同的结果。 例如,

str REGEXP 'a|b|c|d|e'
//not equal to
str REGEXP 'a' OR str REGEXP 'b' OR ...

我对大型数据集执行以下查询,其中'内容'是源代码文件形式的文本。我做内部REGEXP来搜索包含我的关键字列表的任何源文件。一旦我有完整列表,我再次检查它并检查哪个特定关键字绊倒它。这是存在差异的地方;在针对所有关键字进行检查时,某些文件会跳闸,但在针对每个关键字进行检查时,不会跳转任何文件

select
    source_histories.id,
    MAX(source_histories.master_event_id) as master_event_id,
    source_histories.source_file_id,
    source_histories.content REGEXP '[;{}[:space:]]break;' as break,
    source_histories.content REGEXP '[;{}[:space:]]break ' as break_label,
    source_histories.content REGEXP '[;{}[:space:]]continue;' as `continue`,
    source_histories.content REGEXP '[;{}[:space:]]throw ' as throw,
    source_histories.content REGEXP '[;{}[:space:]]return;' as return_void
from
    source_histories,
    (SELECT 
        DISTINCT source_file_id
    from
        source_histories
    where
        ifnull(content, '') REGEXP '[;{}[:space:]]break;|[;{}[:space:]]break |[;{}[:space:]]continue;|[;{}[:space:]]throw |[;{}[:space:]]return;'
    LIMIT 100
    ) as sourceIdList
where
    source_histories.source_file_id = sourceIdList.source_file_id 
group by
    source_histories.source_file_id;

以下是包含此问题的结果部分。如您所见,source_file_id 92和95在单独检查时与任何关键字都不匹配,但在对所有关键字进行检查时必须匹配。我查看了他们的源代码,他们确实包含一个或多个关键字。

id  master_event_id  source_file_id  break break_label  continue  throw  return_void 
256 3260             63              1     0            0         1      0
258 3640             65              1     0            0         0      0
259 3640             66              0     0            0         1      0
320 93722            85              1     0            0         0      0
346 471              92              0     0            0         0      0
360 93731            95              0     0            0         0      0
483 96052            108             1     0            0         0      0
536 1010             112             0     0            0         1      0

有没有人建议我的问题是什么?这是由于轻微的看法,还是mySQL的细微差别?

解: 问题出在我分析数据的顺序上。我找到了符合我标准的独特source_file_id,但不能保证文件的相应最新版本(max master_event_id)也有关键字。以下(无论多慢)是我找到的解决方案。

select
    source_histories.id,
    source_histories.master_event_id as master_event_id,
    source_histories.source_file_id,
    source_histories.content REGEXP '[;{}[:space:]]break;' as break,
    source_histories.content REGEXP '[;{}[:space:]]break ' as break_label,
    source_histories.content REGEXP '[;{}[:space:]]continue;' as `continue`,
    source_histories.content REGEXP '[;{}[:space:]]throw ' as throw,
    source_histories.content REGEXP '[;{}[:space:]]return;' as return_void
from
    source_histories
    inner join
        (select
            source_histories.id,
            MAX(source_histories.master_event_id) as master_event_id,
            source_histories.source_file_id
        from
            source_histories
            inner join
                (SELECT
                    DISTINCT source_file_id
                FROM
                    source_histories
                LIMIT 100
                ) as distinctSHList
            on
                source_histories.source_file_id = distinctSHList.source_file_id
            group by
                source_file_id
        ) as lastestSourceList
    on source_histories.id = lastestSourceList.id
where
    ifnull(content, '') REGEXP '[;{}[:space:]]break;|[;{}[:space:]]break |[;{}[:space:]]continue;|[;{}[:space:]]throw |[;{}[:space:]]return;';

1 个答案:

答案 0 :(得分:1)

问题不在REGEX条款中,而在于您选择的方式。

子查询会考虑给定source_histories的所有source_file_id条记录,而主查询(由于分组)只会为给定的{{source_histories记录1}}考虑到了。

要验证,请从查询中删除source_file_idGROUP BY条款,然后加入MAX;结果应该匹配。

source_histories.id