Mysql 函数FIND_IN_SET
FIND_IN_SET是 MySQL 的一个字符串处理函数用于在逗号分隔的字符串列表中查找指定值的位置。一、函数语法sqlFIND_IN_SET(str, strlist)参数说明str要查找的字符串strlist逗号分隔的字符串列表如A,B,C返回值如果找到返回位置从 1 开始如果没找到返回0如果str或strlist为NULL返回NULL二、基本示例sqlSELECT FIND_IN_SET(B, A,B,C,D); -- 返回 2 SELECT FIND_IN_SET(Z, A,B,C,D); -- 返回 0 SELECT FIND_IN_SET(NULL, A,B,C,D); -- 返回 NULL SELECT FIND_IN_SET(B, NULL); -- 返回 NULL SELECT FIND_IN_SET(B, ); -- 返回 0三、常见使用场景1. 判断某个值是否在逗号分隔的字符串中sql-- 查询所属系统包含 1 的记录 SELECT * FROM vehicle WHERE FIND_IN_SET(1, belonging_system) 0;2. 按逗号分隔字符串排序sql-- 按用户指定的顺序排序如 3,1,2 SELECT * FROM user ORDER BY FIND_IN_SET(id, 3,1,2);3. 结合COALESCE处理 NULLsql-- 如果参数为 NULL查询全部否则按 IN 匹配 SELECT * FROM vehicle WHERE (?1 IS NULL OR FIND_IN_SET(?1, belonging_system) 0);4. 统计某个值出现的次数sql-- 统计 VIN 中包含 L58 的记录数 SELECT COUNT(*) FROM vehicle WHERE FIND_IN_SET(L58, vin) 0;四、在你的场景中使用FIND_IN_SET场景belonging_system是逗号分隔的字符串sql-- 查询 belonging_system 包含 systemId 的所有记录 SELECT * FROM vehicle WHERE FIND_IN_SET(1, belonging_system) 0; -- 结合参数判空 SELECT * FROM vehicle WHERE (?1 IS NULL OR FIND_IN_SET(?1, belonging_system) 0);JPA 原生查询写法javaQuery(value SELECT * FROM vehicle v WHERE (COALESCE(?1, NULL) IS NULL OR FIND_IN_SET(?1, v.belonging_system) 0), nativeQuery true) PageVehicle findBySystemId(Param(systemId) String systemId, Pageable pageable);五、FIND_IN_SETvsIN对比项FIND_IN_SETIN适用场景字段是逗号分隔的字符串字段是单个值用法FIND_IN_SET(A, column) 0column IN (A, B)索引使用❌无法使用索引✅ 可以使用索引性能全表扫描数据量大时慢有索引时快参数传递传单个字符串需要传多个值集合核心区别IN用于多个值的列表匹配FIND_IN_SET用于单个字段中存储的逗号分隔字符串匹配六、性能注意事项⚠️FIND_IN_SET无法使用索引在数据量大时性能较差。数据量性能表现 1 万条✅ 可以接受1 万 ~ 10 万⚠️ 可能变慢 10 万❌ 严重性能问题优化建议改用关联表推荐将belonging_system从逗号分隔字符串改为多对多关联表使用IN或EXISTS查询利用索引使用 JSON 数组MySQL 5.7sql-- 存储为 JSON 数组 SELECT * FROM vehicle WHERE JSON_CONTAINS(belonging_system, 1);使用全文索引sqlALTER TABLE vehicle ADD FULLTEXT(belonging_system); SELECT * FROM vehicle WHERE MATCH(belonging_system) AGAINST(1);七、完整示例sql-- 1. 基本查找 SELECT FIND_IN_SET(2, 1,2,3,4); -- 返回 2 -- 2. 在 WHERE 中使用 SELECT * FROM user WHERE FIND_IN_SET(admin, roles) 0; -- 3. 结合 ORDER BY按指定顺序 SELECT * FROM product WHERE id IN (3,1,2) ORDER BY FIND_IN_SET(id, 3,1,2); -- 4. 结合 CASE SELECT name, CASE WHEN FIND_IN_SET(admin, roles) 0 THEN 管理员 WHEN FIND_IN_SET(user, roles) 0 THEN 普通用户 ELSE 未知 END AS role_name FROM user;八、总结要点说明功能在逗号分隔的字符串中查找值的位置返回值找到返回位置1-based没找到返回 0主要场景判断值是否存在于逗号分隔字段中优点简单直观适合小数据量缺点无法使用索引大数据量时性能差替代方案关联表、JSON 数组、全文索引建议如果belonging_system经常被查询建议改为多对多关联表彻底解决性能问题。如果数据量小 1 万FIND_IN_SET可以接受。