我在我的一个表中有一个列,其中存储了多个由逗号分隔的ID.有没有一种方法可以在查询的"IN"子句中使用此列的值.
列(city)的值类似于6,7,8,16,21,2
我需要使用as
select * from table where e_ID in (Select city from locations where e_Id=?)
Run Code Online (Sandbox Code Playgroud)
我对Crozin的回答感到满意,但我对建议,观点和选择持开放态度.
随意分享您的观点.
Bil*_*win 29
在@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 = ?
Run Code Online (Sandbox Code Playgroud)
这是众所周知的非常表现不佳,因为它做表扫描,评估FIND_IN_SET()函数每一行的组合table和locations.它无法使用索引,也无法改进它.
我知道你说你正在努力充分利用糟糕的数据库设计,但你必须明白这是多么糟糕.
说明:假设我要求您在电话簿中查找每个人,其中第一个,中间或最后一个首字母是"J".在这种情况下,书的排序顺序无法帮助,因为无论如何你必须扫描每一页.
LIKE@fthiella给出的解决方案在性能方面存在类似问题.它无法编入索引.
另请参阅我的答案是否在数据库列中存储分隔列表真的那么糟糕?对于这种存储非规范化数据的方式的其他缺陷.
如果可以创建存储索引的补充表,则可以将位置映射到城市列表中的每个条目:
CREATE TABLE location2city (
location INT,
city INT,
PRIMARY KEY (location, city)
);
Run Code Online (Sandbox Code Playgroud)
假设你有一个所有可能城市的查找表(不仅仅是那些提到的那些城市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;
Run Code Online (Sandbox Code Playgroud)
现在,您可以运行更高效的查询来查找以下内容中的条目table:
SELECT * FROM location2city l
JOIN table t ON t.e_ID = l.city
WHERE l.e_ID = ?;
Run Code Online (Sandbox Code Playgroud)
这可以使用索引.现在您只需要注意任何INSERT/UPDATE/DELETE行locations也会插入相应的映射行location2city.
Jer*_*yth 24
Rather than use IN on your query, use FIND_IN_SET (docs):
SELECT * FROM table
WHERE 0 < FIND_IN_SET(e_ID, (
SELECT city FROM locations WHERE e_ID=?))
Run Code Online (Sandbox Code Playgroud)
The usual caveats about first form normalization apply (the database shouldn't store multiple values in a single column), but if you're stuck with it, then the above statement should help.
fth*_*lla 21
这不使用IN子句,但它应该做你需要的:
Select *
from table
where
CONCAT(',', (Select city from locations where e_Id=?), ',')
LIKE
CONCAT('%,', e_ID, ',%')
Run Code Online (Sandbox Code Playgroud)
但你必须确保它e_ID不包含任何逗号或任何快乐的角色.
例如
CONCAT(',', '6,7,8,16,21,2', ',') returns ',6,7,8,16,21,2,'
e_ID=1 --> ',6,7,8,16,21,2,' LIKE '%,1,%' ? FALSE
e_ID=6 --> ',6,7,8,16,21,2,' LIKE '%,6,%' ? TRUE
e_ID=21 --> ',6,7,8,16,21,2,' LIKE '%,21,%' ? TRUE
e_ID=2 --> ',6,7,8,16,21,2,' LIKE '%,2,%' ? TRUE
e_ID=3 --> ',6,7,8,16,21,2,' LIKE '%,3,%' ? FALSE
etc.
Run Code Online (Sandbox Code Playgroud)
这个用于oracle ..其中字符串连接由wm_concat完成
select * from table where e_ID in (Select wm_concat(city) from locations where e_Id=?)
Run Code Online (Sandbox Code Playgroud)
是的我同意raheel shan ..为了把这个"in"子句放在我们需要将该列放到代码下面的行中,就可以完成这项工作.
select * from table where to_char(e_ID)
in (
select substr(city,instr(city,',',1,rownum)+1,instr(city,',',1,rownum+1)-instr(city,',',1,rownum)-1) from
(
select ','||WM_CONCAT(city)||',' city,length(WM_CONCAT(city))-length(replace(WM_CONCAT(city),','))+1 CNT from locations where e_Id=? ) TST
,ALL_OBJECTS OBJ where TST.CNT>=rownum
) ;
Run Code Online (Sandbox Code Playgroud)
你应该使用
FIND_IN_SET以逗号分隔值的字符串形式返回值的位置
mysql> SELECT FIND_IN_SET('b','a,b,c,d');
-> 2
Run Code Online (Sandbox Code Playgroud)
不知道这是否是你想要完成的.使用MySQL,可以连接GROUP_CONCAT组中的值
你可以尝试这样的事情:
select * from table where e_ID in (Select GROUP_CONCAT(city SEPARATOR ',') from locations where e_Id=?)
Run Code Online (Sandbox Code Playgroud)
您需要"拆分"城市列值.它会像:
SELECT *
FROM table
WHERE e_ID IN (SELECT TO_NUMBER(
SPLIT_STR(city /*string*/
, ',' /*delimiter*/
, 1 /*start_position*/
)
)
FROM locations);
Run Code Online (Sandbox Code Playgroud)
您可以在此处阅读有关MySQL split_str函数的更多信息:http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/
另外,我在这里使用了Oracle的TO_NUMBER函数.请用适当的MySQL函数替换它.
IN需要行,因此使用逗号分隔列进行搜索将无法执行您想要的操作,但如果您提供此类数据('1','2','3'),这将有效,但您无法在您的字段中保存此类数据无论你在列中插入什么,它都会将整个事物作为一个字符串.
| 归档时间: |
|
| 查看次数: |
19435 次 |
| 最近记录: |