我的一个表中有一列,其中存储多个用逗号分隔的ID。有没有一种方法可以在查询的“ IN”子句中使用此列的值。
column(city)的值类似于6,7,8,16,21,2
city
6,7,8,16,21,2
我需要用作
select * from table where e_ID in (Select city from locations where e_Id=?)
我对Crozin的回答感到满意,但我愿意接受建议,观点和选择。
随时分享您的观点。
以@Jeremy Smith的FIND_IN_SET()示例为基础,您可以使用联接来完成此操作,因此不必运行子查询。
SELECT * FROM table t JOIN locations l ON FIND_IN_SET(t.e_ID, l.city) > 0 WHERE l.e_ID = ?
这是众所周知的非常表现不佳,因为它做表扫描,评估FIND_IN_SET()函数 每一 行的组合table和locations。它不能利用索引,也没有办法对其进行改进。
table
locations
我知道您说过您正在尽最大努力利用糟糕的数据库设计,但是您必须了解这有多么严重。
说明:假设我要您查找电话簿中名字开头,中间或最后一个字母为“ J”的所有人。在这种情况下,书的排序顺序是无济于事的,因为无论如何您都必须扫描每一页。
LIKE@fthiella提供的解决方案在性能方面也存在类似问题。无法索引。
LIKE
另请参阅我对在数据库列中存储分隔列表的问题真的那么糟糕吗?对于这种存储非规范化数据的方式的其他陷阱。
如果可以创建补充表来存储索引,则可以将位置映射到城市列表中的每个条目:
CREATE TABLE location2city ( location INT, city INT, PRIMARY KEY (location, city) );
假设您有一个针对所有可能城市的查找表(而不仅仅是提到的城市table),那么您可以忍受效率低下的一次生成映射的麻烦:
INSERT INTO location2city (location, city) SELECT l.e_ID, c.e_ID FROM cities c JOIN locations l ON FIND_IN_SET(c.e_ID, l.city) > 0;
现在,您可以运行效率更高的查询来查找您的条目table:
SELECT * FROM location2city l JOIN table t ON t.e_ID = l.city WHERE l.e_ID = ?;
这可以利用索引。现在,您只需要注意行中的任何INSERT / UPDATE / DELETE行locations也会在中插入相应的映射行location2city。
location2city