我当前的查询如下所示:

SELECT * FROM fiberbox f WHERE f.fiberBox LIKE '%1740 %' OR f.fiberBox LIKE '%1938 %' OR f.fiberBox LIKE '%1940 %'


我环顾四周,找不到类似于LIKE IN()的东西-我设想它的工作方式如下:

SELECT * FROM fiberbox f WHERE f.fiberbox LIKE IN('%140 %', '%1938 %', '%1940 %')


有什么想法吗?我只是以错误的方式思考问题-一些我从未见过的晦涩命令。

MySQL 5.0.77-community-log

评论

在哪里FIND_IN_SET(f.fiberbox,“ 1740,1938,1940”)

FIND_IN_SET不接受%
之类的通配符

#1 楼

REGEXP可能会更有效,但是您必须对其进行基准测试以确保,例如

SELECT * from fiberbox where field REGEXP '1740|1938|1940'; 


评论


我喜欢这个答案-快速,简单,将所有“选项”都按我的意愿放在一行中(易于编辑)。在我定位的较小结果集上,性能完全没有降低。

–迈克尔·威尔士
09年7月14日在19:04

我的表格中有超过一百万行。 REGEX约0.0009,LIKE约0.0005。如果大于5个REGEX,则大约0.0012 ...

–DavidBélanger
2011-11-26 5:24

我遇到了一个问题,即REGEXP的运行速度过快,但是我需要REGEXP的灵活性,以使我的结果集缩小到LIKE所不能提供的范围。我想出了一个混合解决方案,在其中我同时使用了LIKE和REGEXP。尽管REGEXP部分足以为我提供正确的结果,但使用LIKE同样允许MySQL在不得不使用较慢的REGEXP标准之前大大减少结果集。

– mpen
2012年2月15日下午0:11

要从列中获取正则表达式值:(从中选择group_concat(myColumn分隔符'|')。)

– daVe
15年11月28日在1:05

添加到性能数据。在MySql 5.5中,在具有2.29亿行的表中,左第1个词锚了3个字符搜索:REGEXP:16s,LIKE:8.5s; 2个字词:REGEXP:22.1秒;喜欢:9.69; '^(hemoglobin | hematr?ocrit)。*'vs 3 term like:REGEXP:36.3,LIKE:9.59。

–杰西·克拉克(Jesse Clark)
16年3月11日在18:19

#2 楼

保罗·迪克森(Paul Dixon)的回答对我来说非常出色。此外,对于那些对使用REGEXP感兴趣的人,我观察到了一些东西:

使用通配符实现多个LIKE过滤器:

 SELECT * FROM fiberbox WHERE field LIKE '%1740 %'
                           OR field LIKE '%1938 %'
                           OR field LIKE '%1940 %';  


使用REGEXP替代方法:

 SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 |1940 ';


REGEXP引号内和|之间的值。 (OR)运算符被视为通配符。通常,REGEXP将需要通配符表达式,例如(。*)1740(。*)才能用作%1740%。

如果您需要对通配符的放置进行更多控制,请使用以下一些变体:

通过可控通配符放置来实现LIKE:

SELECT * FROM fiberbox WHERE field LIKE '1740 %'
                          OR field LIKE '%1938 '
                          OR field LIKE '%1940 % test';  


使用:

SELECT * FROM fiberbox WHERE field REGEXP '^1740 |1938 $|1940 (.*) test';



在值前放置^表示行的开头。
在值后放置$表示行的末尾。
(。*)的行为与%通配符非常相似。
。表示任何单个字符,但换行符除外。将。
内的()放在*(。*)处会添加一个重复的模式,该模式指示到行末的任何数量的
字符。

有更有效的方法来缩小特定范围匹配,但这需要更多检查正则表达式。注意:并非所有的正则表达式模式都可以在MySQL语句中使用。您需要测试您的模式并查看其工作原理。

最后,要完成多个LIKE和NOT LIKE过滤器:

SELECT * FROM fiberbox WHERE field LIKE '%1740 %'
                          OR field LIKE '%1938 %'
                          OR field NOT LIKE '%1940 %'
                          OR field NOT LIKE 'test %'
                          OR field = '9999';


使用REGEXP替代项:

SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 |^9999$'
                          OR field NOT REGEXP '1940 |^test ';


或混合替代项:

SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 '
                          OR field NOT REGEXP '1940 |^test '
                          OR field NOT LIKE 'test %'
                          OR field = '9999';


注意我将NOT集合分开在哪里过滤。我尝试使用否定模式,前瞻性模式等。但是,这些表达式似乎未产生期望的结果。在上面的第一个示例中,我使用^ 9999 $表示完全匹配。这使您可以在同一表达式中添加具有通配符匹配项的特定匹配项。但是,您也可以混合使用这些类型的语句,如列出的第二个示例中所示。

关于性能,我对现有表进行了一些次要测试,发现我的变体之间没有差异。但是,我认为性能可能是更大的数据库,更大的字段,更大的记录数和更复杂的过滤器的问题。

一如既往,请使用上面的逻辑。

如果您想了解有关正则表达式的更多信息,建议您将www.regular-expressions.info作为一个很好的参考网站。

评论


请记住,值为NULL的字段与REGEXP不匹配。您可以使用IFNULL解决此问题。在哪里IFNULL(field,'')NOT REGEXP'1740 | 1938'

–user1026130
2013年6月18日18:25



@DanyMarcoux如果我想使用(。*),但它应该像FIELDNAME LIKE'%%'一样,如何与regexp一起使用,以便在传递空字符串时使用。它应该获取所有记录。

– shzyincu
16 Jul 28'14:09



不喜欢'%1940%'的WHERE字段或不喜欢'测试%'的字段将始终返回所有行。这可能是导致未产生您提到的预期结果的原因吗?

– Herbert Van-Vliet
2月29日下午21:35

#3 楼

您可以创建一个内联视图或一个临时表,并用您的值填充它并发出以下命令:

SELECT  *
FROM    fiberbox f
JOIN    (
        SELECT '%1740%' AS cond
        UNION ALL
        SELECT '%1938%' AS cond
        UNION ALL
        SELECT '%1940%' AS cond
        ) с
ON      f.fiberBox LIKE cond


但是,它可以为fiberbox返回多行类似于'1740, 1938',因此此查询可以更好地适合您:

SELECT  *
FROM    fiberbox f
WHERE   EXISTS
        (
        SELECT  1
        FROM    (
                SELECT '%1740%' AS cond
                UNION ALL
                SELECT '%1938%' AS cond
                UNION ALL
                SELECT '%1940%' AS cond
                ) с
        WHERE   f.fiberbox LIKE cond
        )


#4 楼

带值列表的正则表达式方式

SELECT * FROM table WHERE field regexp concat_ws("|",
"111",
"222",
"333");


#5 楼

抱歉,在mysql中没有类似于LIKE IN的操作。

如果要在没有联接的情况下使用LIKE运算符,则必须采用以下方式:

(field LIKE value OR field LIKE value OR field LIKE value)


您知道, MySQL不会优化该查询,仅供参考。

#6 楼

只需注意尝试使用REGEXP来使用“ LIKE IN”功能的任何人。

IN允许您执行以下操作:

field IN (
'val1',
'val2',
'val3'
)


在REGEXP中,这赢了不起作用

REGEXP '
val1$|
val2$|
val3$
'


它必须像这样一行:

REGEXP 'val1$|val2$|val3$'


#7 楼

翻转操作数

'a,b,c' like '%'||field||'%'


评论


当你有一些字段明确地等于例如。 grads'a','b','c'的枚举,但不包括ab,ac或bc的枚举创建表x(en enum('a,b,c')));插入x值('a'), ('b')en只是a或b通过翻转操作选择* from,x来执行此方法,其中像concat('%',en,'%')这样的'a,c'在SQL指令中可以更安全转义字符,例如$ ^等。

–user1883132
2012-12-15 15:05



这不是等效的,在一般情况下将不起作用。如果您知道该字段只能是a,b或c,则应使用字段IN(“ a”,“ b”,“ c”)。但是在一般情况下,这永远不能替换字段LIKE'%a%'或字段LIKE'%b%'或...,因为字段本身可以像魔术一样使'Magic'LIKE'%a%'变为真实,但表达式'a,b,c'就像'%magic%'一样。

– ADTC
17-10-21在1:34

#8 楼

这是正确的:

SELECT * FROM table WHERE field regexp concat_ws("|",(
"111",
"222",
"333"
));


#9 楼

提示:

我更喜欢使用变体RLIKE(与REGEXP完全相同的命令),因为它听起来更像自然语言,而且更短;好吧,只有1个字符。

“ R”前缀用于Reg。当然可以。

#10 楼

您可以在正则表达式的帮助下获得所需的结果。

SELECT fiberbox from fiberbox where fiberbox REGEXP '[1740|1938|1940]';


我们可以测试以上查询,请单击SQL小提琴

SELECT fiberbox from fiberbox where fiberbox REGEXP '[174019381940]';


我们可以测试以上查询,请单击SQL小提琴

评论


这是不正确的正则表达式。 [...]是一个字符集,意味着该集中的任何字符都足以被视为匹配项。因此,任何具有数字'0、1、3、4、7、8、9或|的值竖线字符将与此匹配。

–马丁·彼得斯(Martijn Pieters)♦
18年7月5日在15:07

#11 楼

您也可以这样使用:
SELECT * FROM fiberbox WHERE fiber IN('140 ', '1938 ', '1940 ')