MySQL查询在逗号分隔的字符串中查找值

MySQL查询在逗号分隔的字符串中查找值,sql,mysql,database,Sql,Mysql,Database,我在我的表格SHIRTS中有一个字段COLORS(varchar(50)),它包含一个逗号分隔的字符串,如1,2,5,12,15,。表示可用颜色的每个数字 运行查询select*from shirts where colors像“%1%”以获取所有红色衬衫(color=1),我还将获取颜色为灰色(=12)和橙色(=15)的衬衫 我应该如何重写查询,以便is只选择颜色1,而不是选择包含数字1的所有颜色?如果您使用的是MySQL,那么有一个方法REGEXP可以使用 那么你会使用: SELECT *

我在我的表格
SHIRTS
中有一个字段
COLORS(varchar(50))
,它包含一个逗号分隔的字符串,如
1,2,5,12,15,
。表示可用颜色的每个数字

运行查询
select*from shirts where colors像“%1%”
以获取所有红色衬衫(color=1),我还将获取颜色为灰色(=12)和橙色(=15)的衬衫


我应该如何重写查询,以便is只选择颜色1,而不是选择包含数字1的所有颜色?

如果您使用的是MySQL,那么有一个方法REGEXP可以使用

那么你会使用:

SELECT * FROM `shirts` WHERE `colors` REGEXP '\b1\b'
看看MySQL的函数

SELECT * 
    FROM shirts 
    WHERE FIND_IN_SET('1',colors) > 0

实际上,您应该修复数据库架构,以便有三个表:

shirt: shirt_id, shirt_name
color: color_id, color_name
shirtcolor: shirt_id, color_id
然后,如果要查找所有红色衬衫,可以执行如下查询:

SELECT *
FROM shirt, color
WHERE color.color_name = 'red'
  AND shirt.shirt_id = shirtcolor.shirt_id
  AND color.color_id = shirtcolor.color_id

经典的方法是在左侧和右侧添加逗号:

select * from shirts where CONCAT(',', colors, ',') like '%,1,%'
但也能起作用:

select * from shirts where find_in_set('1',colors) <> 0
从衬衫中选择*,在衬衫集中找到衣服('1',颜色)0
在这种情况下是你的朋友吗

select * from shirts where FIND_IN_SET(1,colors) 

这肯定会起作用,我确实尝试过:

lwdba@localhost (DB test) :: DROP TABLE IF EXISTS shirts;
Query OK, 0 rows affected (0.08 sec)

lwdba@localhost (DB test) :: CREATE TABLE shirts
    -> (<BR>
    -> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> ticketnumber INT,
    -> colors VARCHAR(30)
    -> );<BR>
Query OK, 0 rows affected (0.19 sec)

lwdba@localhost (DB test) :: INSERT INTO shirts (ticketnumber,colors) VALUES
    -> (32423,'1,2,5,12,15'),
    -> (32424,'1,5,12,15,30'),
    -> (32425,'2,5,11,15,28'),
    -> (32426,'1,2,7,12,15'),
    -> (32427,'2,4,8,12,15');
Query OK, 5 rows affected (0.06 sec)
Records: 5  Duplicates: 0  Warnings: 0

lwdba@localhost (DB test) :: SELECT * FROM shirts WHERE LOCATE(CONCAT(',', 1 ,','),CONCAT(',',colors,',')) > 0;
+----+--------------+--------------+
| id | ticketnumber | colors       |
+----+--------------+--------------+
|  1 |        32423 | 1,2,5,12,15  |
|  2 |        32424 | 1,5,12,15,30 |
|  4 |        32426 | 1,2,7,12,15  |
+----+--------------+--------------+
3 rows in set (0.00 sec)
lwdba@localhost(DB测试):如果存在,则丢弃表格;
查询正常,0行受影响(0.08秒)
lwdba@localhost(DB测试)::创建桌面衬衫
->(
->id INT NOT NULL自动递增主键, ->票号整数, ->颜色VARCHAR(30) -> );
查询正常,0行受影响(0.19秒) lwdba@localhost(DB测试):插入衬衫(票号、颜色)值 -> (32423,'1,2,5,12,15'), -> (32424,'1,5,12,15,30'), -> (32425,'2,5,11,15,28'), -> (32426,'1,2,7,12,15'), -> (32427,'2,4,8,12,15'); 查询正常,5行受影响(0.06秒) 记录:5个重复:0警告:0 lwdba@localhost(DB测试)::从位于以下位置的衬衫中选择*(CONCAT(',',1',,'),CONCAT(',',,colors,,'))>0; +----+--------------+--------------+ |id |票号|颜色| +----+--------------+--------------+ | 1 | 32423 | 1,2,5,12,15 | | 2 | 32424 | 1,5,12,15,30 | | 4 | 32426 | 1,2,7,12,15 | +----+--------------+--------------+ 一组3行(0.00秒)

试试看

如果颜色集或多或少是固定的,最有效也是最可读的方法是在应用程序中使用字符串常量,然后在查询中使用MySQL的
set
键入
FIND\u in\u set('red',colors)
。当使用
SET
type with时,MySQL使用一个整数存储所有值,并使用二进制
和“
操作检查是否存在值,这比扫描逗号分隔的字符串更有效


SET('red'、'blue'、'green')
中,
'red'
将作为
1
内部存储,
'blue'
将作为
2
内部存储,
'green'
将作为
4
内部存储。值
'red,blue'
将存储为
3
1 | 2
)和
'red,green'
存储为
5
1 | 4
)。

所有答案都不正确,请尝试以下操作:

select * from shirts where 1 IN (colors);
从衬衫中选择*,在衬衫集中找到衣服('1',颜色)0

适用于我

您可以通过以下功能实现此功能

DELIMITER ||
CREATE FUNCTION `TOTAL_OCCURANCE`(`commastring` TEXT, `findme`     VARCHAR(255)) RETURNS int(11)
NO SQL
-- SANI: First param is for comma separated string and 2nd for string to find.
return ROUND (   
    (
        LENGTH(commastring)
        - LENGTH( REPLACE ( commastring, findme, "") ) 
    ) / LENGTH(findme)        
);
运行以下查询以创建函数

DELIMITER ||
CREATE FUNCTION `TOTAL_OCCURANCE`(`commastring` TEXT, `findme`     VARCHAR(255)) RETURNS int(11)
NO SQL
-- SANI: First param is for comma separated string and 2nd for string to find.
return ROUND (   
    (
        LENGTH(commastring)
        - LENGTH( REPLACE ( commastring, findme, "") ) 
    ) / LENGTH(findme)        
);
然后像这样调用这个函数

msyql> select TOTAL_OCCURANCE('A,B,C,A,D,X,B,AB', 'A');

1。对于MySQL:

SELECT FIND_IN_SET(5, columnname) AS result 
FROM table
SELECT * 
FROM TABLENAME f
WHERE 'searchvalue' = ANY (string_to_array(COLUMNNAME, ','))
2.对于Postgres SQL:

SELECT FIND_IN_SET(5, columnname) AS result 
FROM table
SELECT * 
FROM TABLENAME f
WHERE 'searchvalue' = ANY (string_to_array(COLUMNNAME, ','))
示例

select * 
from customer f
where '11' = ANY (string_to_array(customerids, ','))

我想,您可以通过regex实现这一点,但更好的解决方案是将衬衫颜色分解为单独的表(颜色),并使用联接表(衬衫颜色)使用color/shirt的ID来链接它们。我不敢相信有6个答案没有一个提到MySQL的SET数据类型。检查这个:我尝试在\ u SET中查找\ u,但无论我输入的颜色值如何,它都返回相同的结果。。。有什么建议吗?@bikey77:也许这就是问题所在,它说:如果第一个参数包含逗号(“,”)字符,则此函数无法正常工作。我错了,这是由于相同的伪值导致的逻辑错误。它很好用。谢谢@在我找到你的答案之前,我并没有挣扎,但你的工作很有魅力。。。非常感谢。它会对性能产生影响,因为未使用“在集合中查找”index@Blindy:仅当假定OP对数据库架构具有编辑权限时,才是如此;有时间重新设计数据库、迁移数据和重构所有客户机;而且这个查询复杂性的降低超过了应用程序其余部分复杂性的增加。@Andomar,当他再次遇到行检索的大小限制,他的“记录”将被剪裁时,真正的乐趣就开始了@盲目:你没有抓住重点;我并不是说他有最好的解决方案,只是不是每个人都有按照自己的喜好重新设计环境的自由。我同意@Andomarc的观点。我不知道这是怎么回事,尽管我很确定这是我的错。感谢mil mate.find_in_set对于大表来说太慢了它可以工作感谢软件:find in set不使用表上的索引。嘿@RolandmySqldba,我测试了你的查询,它可以工作,但我需要对它做一些更改。假设我想得到列中颜色值为1,2的所有衬衫。