MySQL find_in_set 具有多个搜索字符串

问题描述 投票:0回答:7

我发现 find_in_set 只能通过单个字符串搜索:-

find_in_set('a', 'a,b,c,d')

在上面的示例中,“a”是唯一用于搜索的字符串。

有没有办法使用 find_in_set 类型的功能并按多个字符串进行搜索,例如:-

find_in_set('a,b,c', 'a,b,c,d')

在上面的例子中,我想通过三个字符串“a,b,c”进行搜索。

我看到的一种方法是使用 OR

find_in_set('a', 'a,b,c,d') OR find_in_set('b', 'a,b,c,d') OR find_in_set('b', 'a,b,c,d')

除了这个还有其他办法吗?

sql mysql search
7个回答
134
投票

没有原生函数可以做到这一点,但您可以使用以下技巧来实现您的目标

WHERE CONCAT(",", `setcolumn`, ",") REGEXP ",(val1|val2|val3),"

16
投票

MySQL 函数

find_in_set()
只能搜索一组字符串中的一个字符串。

第一个参数是一个字符串,因此无法让它将逗号分隔的字符串解析为字符串(您根本不能在 SET 元素中使用逗号!)。第二个参数是一个 SET,它又由逗号分隔的字符串表示,因此您希望

find_in_set('a,b,c', 'a,b,c,d')
工作正常,但根据定义,它肯定无法在任何 SET 中找到字符串
'a,b,c'
- 它包含逗号。


2
投票

您也可以使用此自定义功能

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, ''); 

DELIMITER $$
    CREATE FUNCTION `FIND_SET_EQUALS`(`s1` VARCHAR(200), `s2`  VARCHAR(200)) 
    RETURNS TINYINT(1)
    LANGUAGE SQL
    BEGIN
          DECLARE a INT Default 0 ;
            DECLARE isEquals TINYINT(1) Default 0 ;
          DECLARE str VARCHAR(255);
          IF s1 IS NOT NULL AND s2 IS NOT NULL THEN
             simple_loop: LOOP
                 SET a=a+1;
                 SET str= SPLIT_STR(s2,",",a);
                 IF str='' THEN
                    LEAVE simple_loop;
                 END IF;
                 #Do  check is in set
                 IF FIND_IN_SET(str, s1)=0 THEN
                    SET isEquals=0;
                     LEAVE simple_loop;
                 END IF;
                 SET isEquals=1;
            END LOOP simple_loop;
          END IF;
        RETURN isEquals;
    END;
    $$
    DELIMITER ;

SELECT FIND_SET_EQUALS('a,c,b', 'a,b,c')- 1
SELECT FIND_SET_EQUALS('a,c', 'a,b,c')- 0
SELECT FIND_SET_EQUALS(null, 'a,b,c')- 0

1
投票

哇,我很惊讶这里没有人提到过这一点。
简而言之,如果您知道成员的顺序,那么只需在单个按位运算中查询即可。

SELECT * FROM example_table WHERE (example_set & mbits) = mbits;

说明:

如果我们有一个按以下顺序包含成员的集合:“HTML”,“CSS”,“PHP”,“JS”...等。
这就是它们在 MySQL 中的解释方式:

"HTML" = 0001 = 1
"CSS"  = 0010 = 2
"PHP"  = 0100 = 4
"JS"   = 1000 = 16

例如,如果您想查询集合中包含“HTML”和“CSS”的所有行,那么您将编写

SELECT * FROM example_table WHERE (example_set & 3) = 3;

因为

0011
3
,既是
0001
"HTML"
又是
0010
"CSS"

您的集合仍然可以使用其他方法进行查询,例如 REGEXP 、 LIKE 、 FIND_IN_SET() 等。使用您需要的任何东西。


0
投票

@Pavel Perminov 的惊人回答! - 还有 @doru 的精彩评论,用于动态检查..

从那里我为 PHP 代码制作了

CONCAT(',','" . $country_lang_id . "', ',') REGEXP CONCAT(',(', REPLACE(YourColumnName, ',', '|'), '),')
下面的查询对于正在寻找现成的 PHP 代码的人来说可能很有用。

$country_lang_id = "1,2";

$sql = "select a.* from tablename a where CONCAT(',','" . $country_lang_id . "', ',') REGEXP CONCAT(',(', REPLACE(a.country_lang_id, ',', '|'), '),') ";

-4
投票

您还可以使用类似的命令,例如:

where setcolumn like '%a,b%'

where 'a,b,c,d' like '%b,c%'

这在某些情况下可能有效。


-10
投票

您可以使用 in 从两个值中查找匹配值

SELECT * FROM table WHERE  myvals in (a,b,c,d)
© www.soinside.com 2019 - 2024. All rights reserved.