MySQL-从一列中选择子字符串,而不会从同一列中捕获相似的子字符串

时间:2019-02-02 02:31:14

标签: mysql sql select substring

在MySQL表中,我有一个名为ShareID的VARCHAR列。

  • 如果第1行的ShareID值包含 1
  • 形式的字符串
  • ,第2行的ShareID值包含 10,1
  • 形式的字符串
  • ,第3行的ShareID值包含 111,12 形式的字符串。

我想获取ShareID为 1 的所有行。即仅此处的第一行和第二行。

我尝试使用LIKE命令,如下所示:

SELECT * FROM tablename WHERE ShareWithID LIKE '1%';

但这将捕获其中包含数字 1 的所有行,即不是我想要的行#3。

我想运行一条仅返回上面的行#1和#2的命令,因为其中包含的共享ID为 1

我尝试了各种命令(包括REGEXP和IN),并管理了一种“快速”解决方案,在该解决方案中,我在ShareID列中的每个数字后都添加了逗号,包括最后一个(即 10,1, ),然后执行以下命令:

SELECT * FROM tablename WHERE ShareWithID LIKE '%1,%';

但我宁愿使用适当的解决方案,而不要使用固定的解决方案。

任何指导都将受到欢迎。

3 个答案:

答案 0 :(得分:2)

您不应将数字列表存储在以逗号分隔的字符串中。这是一个非常糟糕的主意:

  • 数字应存储为数字,而不是字符串。
  • 您的电话号码似乎是id。 ID应该定义了明确的外键。
  • SQL(通常)具有糟糕的字符串处理功能。
  • SQL无法使用字符串操作优化查询。
  • SQL具有一种存储列表的好方法。它称为

尽管如此,有时候,我们在设计数据库的过程中确实被其他人束之高阁。 MySQL在这种情况下具有便捷的功能:

where find_in_set(1, ShareWithID) > 0

如果字符串中有空格,则需要删除它们:

where find_in_set(1, replace(ShareWithID, ' ', '')) > 0

答案 1 :(得分:1)

  

...将使用内置功能

FIND_IN_SET()实际上不用于包含逗号分隔列表的字符串。它旨在与MySQL的SET data type一起使用。因此,名称为FIND_IN_SET(),而不是FIND_IN_COMMA_SEPARATED_LIST()

  

当原始“表”中的一列也可以完成这项工作时,节省了浪费时间来构建25万行的“表”(是它??)来照顾几列ID。 >

对于MySQL,

25万​​行不是问题。我管理给定表中具有 billions 行的数据库。如果您对索引进行基本的查询优化,那么对25万行的表中的大多数查询就可以了。

而使用逗号分隔的列表,则可能会破坏优化查询的任何机会。索引无助于搜索可能不是字符串最左前缀的子字符串,而在以逗号分隔的列表中搜索数字基本上是在搜索子字符串。

您正在使用逗号分隔的列表来使查询无法优化。每个使用FIND_IN_SET()的查询都将是一个表扫描,与表中的行数呈线性关系会变慢。

除索引外,使用逗号分隔的列表还有其他缺点,这是我在对这则旧帖子的回答中写到的:Is storing a delimited list in a database column really that bad?

  

我宁愿使用适当的解决方案,也不要使用笼罩的解决方案。

然后每行存储一个ID。在关系数据库中,这是正确的解决方案。

答案 2 :(得分:0)

此问题的解决方案是将Gordon Linoff对FIND_IN_SET命令的建议与有关表列的正确配置结合使用,如下所示:

SELECT * FROM tablename WHERE FIND_IN_SET('1', ShareWithID);

然而,因为FIND_IN_SET命令可以找到的字符串中的位置一个的 逗号分隔 的字符串列表,必须确保的是,列的内容包含逗号每个项目后,不包含逗号后的空格。

因此,与上述命令结合使用的此列内容将返回“ 0”行: 111,1

此列内容将返回“ 1”行: 111,1

这将是: 33,1

这是: 44,1,415