在 MySQL 表中搜索包含 CSV 数据的列中是不是存在输入值
Posted
技术标签:
【中文标题】在 MySQL 表中搜索包含 CSV 数据的列中是不是存在输入值【英文标题】:Searching a column containing CSV data in a MySQL table for existence of input values在 MySQL 表中搜索包含 CSV 数据的列中是否存在输入值 【发布时间】:2011-02-20 20:53:50 【问题描述】:我在 mysql 中有一个表 ITEM,它存储数据如下:
ID FEATURES
--------------------
1 AB,CD,EF,XY
2 PQ,AC,A3,B3
3 AB,CDE
4 AB1,BC3
--------------------
作为输入,我将得到一个 CSV 字符串,例如“AB,PQ”。我想获取包含 AB 或 PQ 的记录。我意识到我们必须编写一个 MySQL 函数来实现这一点。因此,如果我们在 MySQL 中定义了这个神奇的函数 MATCH_ANY 来执行此操作,那么我将简单地执行如下 SQL:
select * from ITEM where MATCH_ANY(FEAURES, "AB,PQ") = 0
上述查询将返回记录 1、2 和 3。
但是我在实现这个函数时遇到了各种各样的问题,因为我意识到 MySQL 不支持数组并且没有简单的方法来基于分隔符分割字符串。
改造桌子对我来说是最后的选择,因为它涉及很多问题。
我可能还想执行包含多个 MATCH_ANY 函数的查询,例如:
select * from ITEM where MATCH_ANY(FEATURES, "AB,PQ") = 0 and MATCH_ANY(FEATURES, "CDE")
在上述情况下,我们会得到记录 (1, 2, 3) 和 (3) 的交集,这将是 3。
非常感谢任何帮助。
谢谢
【问题讨论】:
【参考方案1】:只是一个想法:
必须在 SQL 中完成吗?这是您通常希望用 php 或 Python 或您用来与数据库交互的任何语言编写的那种东西。
这种方法意味着您可以使用所需的任何复杂逻辑构建查询字符串,然后只需提交普通 SQL 查询,而不是尝试在 SQL 中构建过程。
本
【讨论】:
嗯,我真正想做的是预测符合给定条件的记录数。此查询将通过 PHP 使用 AJAX 触发。因此,返回结果越快,对我来说就越好。这让我只有一个选择 - 进行单个数据库命中。这就是我感觉卡住的地方!是的,我可以使用 PHP 构造复杂的查询字符串。但我无法理解这个查询字符串会是什么样子。【参考方案2】:select *
from ITEM where
where CONCAT(',',FEAURES,',') LIKE '%,AB,%'
or CONCAT(',',FEAURES,',') LIKE '%,PQ,%'
或创建一个自定义函数来执行您的 MATCH_ANY
【讨论】:
【参考方案3】:首先,数据库当然不应该包含逗号分隔值,但希望您已经意识到这一点。如果表格被规范化,您可以使用如下查询轻松获取项目:
select distinct i.Itemid
from Item i
inner join ItemFeature f on f.ItemId = i.ItemId
where f.Feature in ('AB', 'PQ')
可以匹配逗号分隔值中的字符串,但效率不高:
select Id
from Item
where
instr(concat(',', Features, ','), ',AB,') <> 0 or
instr(concat(',', Features, ','), ',PQ,') <> 0
【讨论】:
你成功了!谢谢古法!我担心使用 LIKE 或 RLIKE,因为众所周知,这两种方法本质上都比较慢。至少比简单的 INSTR 慢。我基于这个逻辑编写了我的动态查询生成器,它就像一个魅力。我确实理解这种表格模型在规范化方面不是很正确。但这是我目前能提供的最好的。 @Adarsh:是的,它比like
稍微快一点,但它仍然不能在字段上使用任何索引,所以它永远不会很快。【参考方案4】:
或者,考虑使用 RLIKE()
select *
from ITEM
where ','+FEATURES+',' RLIKE ',AB,|,PQ,';
【讨论】:
【参考方案5】:对于所有 REGEXP 爱好者,我想我会添加这个作为解决方案:
SELECT * FROM ITEM WHERE FEATURES REGEXP '[[:<:]]AB|PQ[[:>:]]';
以及区分大小写:
SELECT * FROM ITEM WHERE FEATURES REGEXP BINARY '[[:<:]]AB|PQ[[:>:]]';
对于第二个查询:
SELECT * FROM ITEM WHERE FEATURES REGEXP '[[:<:]]AB|PQ[[:>:]]' AND FEATURES REGEXP '[[:<:]]CDE[[:>:]];
干杯!
【讨论】:
工作就像一个魅力,它为我节省了大量的代码和一个小时的开发时间。我建议其他人也使用这种方法,因为它很紧凑,并且只是 'where' 子句下的一个条件。以上是关于在 MySQL 表中搜索包含 CSV 数据的列中是不是存在输入值的主要内容,如果未能解决你的问题,请参考以下文章