简体   繁体   English

在单个查询中搜索逗号分隔的MySQL列中的多个值

[英]Searching multiple values in a Comma-Separated MySQL column in a single query

I am fully aware of how bad it is to have Delimited Lists in a Table Column, instead of normalizing data into multiple tables. 完全知道在表列中包含定界列表而不是将数据标准化为多个表是多么糟糕

Although, I do have a table structure designed years ago , which I will re-design soon . 虽然,我确实有几年前设计的表格结构,但是我很快会重新设计
Simplified, it looks like this: 简化后,它看起来像这样:

Table: Newsletters
+------------+---------------+
| subject    | mailing_lists |
+------------+---------------+
| A Test     | 1,2           |
| More Tests | 2,3           |
+------------+---------------+ 

You can see it in this SQLFiddle , if you prefer to. 如果愿意,可以在此SQLFiddle中看到它。

Recently, I gave my users the option to write a delimited list of mailing list ids (like 1,3) , as a feature to select which newsletters to show in a view. 最近,我为我的用户提供了写一个分隔列表的邮件列表ID (例如1,3)的选项 ,以选择在视图中显示哪些新闻通讯。
(eg Only show newsletters that were sent to lists with id 1 or 3) (例如,仅显示已发送到ID为1或3的列表的新闻通讯)

So: A table column with a delimited list of ids, and delimited ids as an input. 因此: 具有分隔ID列表和分隔ID作为输入的表列。

This would obviously be much easier if the tables were normalized. 如果将表格标准化,这显然会容易得多。

So, I solved this in PHP, by exploding the input ids and iterating them to create a query like the one in the fiddle mentioned above , which looks like this: 因此,我在PHP中解决了这一问题,方法是分解输入id并对其进行迭代,以创建一个查询,就像上面提到小提琴中的查询一样,如下所示:

SELECT * FROM `newsletters`
  WHERE FIND_IN_SET("1", `mailing_lists`) > 0
     OR FIND_IN_SET("3", `mailing_lists`) > 0

This query perfectly fetches the data I want to get, but I can only create it programmatically, since I have to add a new condition for each id in my delimited list. 该查询可以完美地获取我想要获取的数据,但是我只能以编程方式创建它,因为我必须为定界列表中的每个ID添加新条件。

Question is: Out of pure curiosity: Is there a way to avoid the loop in PHP, and make a query without splitting the ids in code? 问题是: 出于纯粹的好奇心:是否有一种方法可以避免PHP中的循环,并在不拆分代码中ID的情况下进行查询?

After the very useful post by rakeshjain , I managed to transform my query into this: rakeshjain发表了非常有用的文章rakeshjain ,我设法将查询转换为以下内容:

SELECT * FROM (SELECT *,
               `mailing_lists` REGEXP REPLACE("1,3", ',', '(\\,|$)|')
                  as haslists
               FROM `newsletters` B) A
  WHERE A.haslists = 1

In the above, I assume that "1,3" is the value provided by the user. 在上面,我假设“ 1,3”是用户提供的值。
Here is the solved fiddle: http://sqlfiddle.com/#!2/4621b0/19 这是解决的小提琴: http ://sqlfiddle.com/#!2/ 4621b0/19

Thank you rakeshjain ! 谢谢rakeshjain

Yes, there is a way to avoid the loop. 是的,有一种避免循环的方法。 Just normalize your database structure. 只需规范化数据库结构即可。

Table "Subjects" subjectID (INT(11), auto_increment)) | 表“主题” subjectID(INT(11),auto_increment))| subject (varchar(255)) 主题(varchar(255))

Table "MailingLists" listID (INT(11), auto_increment) | 表“ MailingLists”的listID(INT(11),auto_increment)| listName 列表名称

Table "Subjects2Lists" (many to many) subjectID (index) | 表“ Subjects2Lists”(多对多)subjectID(索引)| listID (index) listID(索引)

So you can get every single list ID by executing a simple select / join statement. 因此,您可以通过执行简单的select / join语句来获取每个列表ID。

SELECT 
    list.listID, 
    names.listName 
FROM 
    Subject2Lists AS list 
LEFT JOIN 
    MailingLists AS names 
    ON (list.listID = names.listID) 
WHERE 
    subjectID = 1 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM