在mysql项目开发中,多条件筛选是业务查询的核心场景,比如商品列表按分类、价格区间、销量排序筛选,用户列表按状态、注册时间、所属部门筛选等。合理的多条件筛选实现方式和对应的查询优化手段,直接影响系统的响应速度和用户体验。
mysql多条件筛选的实现方式
基础静态多条件筛选
如果筛选条件是固定的,可以直接在WHERE子句中用逻辑运算符拼接条件,常用的逻辑运算符有AND、OR、NOT,同时可以配合比较运算符、范围查询、模糊查询等使用。
比如查询价格大于100、库存大于0且分类为电子产品的商品,SQL语句如下:
-- 静态多条件筛选示例 SELECT id, name, price, stock FROM product WHERE price > 100 AND stock > 0 AND category = '电子产品' AND status = 1;
动态多条件筛选
实际项目中筛选条件往往是动态的,用户可能只选部分条件,未选的条件不需要参与筛选。这种场景可以用两种方式实现,一种是拼接SQL字符串,另一种是配合IF或者CASE函数处理空值条件。
拼接SQL的方式需要注意SQL注入风险,建议使用预编译语句。以下是使用预编译实现动态条件的示例,假设用户可能传入分类、最小价格、最大价格三个可选条件:
-- 动态多条件筛选预编译示例
SELECT id, name, price, stock
FROM product
WHERE 1=1
<if test="category != null">
AND category = #{category}
</if>
<if test="minPrice != null">
AND price >= #{minPrice}
</if>
<if test="maxPrice != null">
AND price <= #{maxPrice}
</if>
AND status = 1;
如果是直接在mysql客户端执行,也可以用COALESCE函数处理空条件,示例如下:
-- 用COALESCE处理动态空条件 SET @category = NULL; SET @min_price = 50; SET @max_price = 200; SELECT id, name, price, stock FROM product WHERE (category = @category OR @category IS NULL) AND (price >= @min_price OR @min_price IS NULL) AND (price <= @max_price OR @max_price IS NULL) AND status = 1;
多条件筛选场景的查询优化方法
合理设计联合索引
多条件筛选的性能核心在于索引的使用,建议根据筛选条件的使用频率和顺序设计联合索引。联合索引遵循最左前缀原则,比如筛选条件经常是category + price + stock的顺序,那么可以创建INDEX idx_category_price_stock (category, price, stock)的联合索引。
需要注意避免在索引列上使用函数或者运算,比如WHERE YEAR(create_time) = 2023会导致索引失效,应该改成WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01'。
优化条件顺序和逻辑
在WHERE子句中,应该把过滤性强的条件放在前面,这样可以先过滤掉大部分数据,减少后续条件的判断成本。同时尽量避免使用OR连接不同字段的条件,OR可能导致索引失效,可以改成UNION查询。
比如以下使用OR的语句:
-- 低效的OR查询 SELECT * FROM product WHERE category = '电子产品' OR price < 50;
可以优化为:
-- 优化后的UNION查询 SELECT * FROM product WHERE category = '电子产品' UNION ALL SELECT * FROM product WHERE price < 50 AND category != '电子产品';
分析执行计划调整语句
使用EXPLAIN关键字可以查看SQL的执行计划,重点关注type、key、rows、Extra字段。type最好是ref或者range,如果是ALL说明全表扫描,需要优化;key显示实际使用的索引,如果是NULL说明没有使用索引;rows是预估扫描的行数,数值越小越好;Extra中如果出现Using filesort或者Using temporary说明需要优化排序或者临时表。
执行计划分析示例:
-- 查看执行计划 EXPLAIN SELECT id, name, price FROM product WHERE category = '电子产品' AND price > 100 AND stock > 0;
避免返回多余数据
多条件筛选查询时,尽量不要用SELECT *,只查询需要的字段,减少数据读取和传输的成本。如果数据量很大,可以配合分页查询,避免一次性返回过多数据。
分页查询示例:
-- 分页查询示例,每页10条,查询第2页 SELECT id, name, price FROM product WHERE category = '电子产品' AND price > 100 LIMIT 10 OFFSET 10;
常见问题注意事项
一是模糊查询LIKE的使用,前缀模糊匹配LIKE '%关键词'会导致索引失效,后缀匹配LIKE '关键词%'可以使用索引,如果需要前缀匹配可以考虑使用全文索引。
二是IN和NOT IN的使用,IN的条件值过多时会导致性能下降,建议控制在合理范围内,NOT IN如果子查询返回大量数据也容易出问题,可以改成NOT EXISTS。
三是数据类型匹配,筛选条件的类型和字段类型要保持一致,比如字段是整型,就不要传入字符串类型的条件,否则会触发隐式类型转换导致索引失效。