sqlite 中的or 和 and

本文解析了SQL查询中AND与OR的运算优先级及其可能导致的误解。通过实例说明如何正确使用括号来确保查询符合预期,并提供了AND与OR运算符的具体应用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于 sql的where子句中包含多个and和or是计算顺序问题,SQL在处理操作时会优先处理and操作,这就是很多人会得到很多错误的原因,举个例子:

加入有表product字段如下:id、product_id、product_price、product_name

现在要查找产品号为100或者101,并且价格大于200的商品,你可能会这样做:

select * from product where product_id = 100 or product_id = 101 and product_price > 200

这是错误的,SQL会这样理解,SQL首先进行and 的操作,最后 就成了这个意思:查找 产品号为101并且价格大于200 或者 产品号为100 的商品。

解决办法很简答,只要使用圆括号就行了:

select * from product where (product_id = 100 or product_id = 101and product_price > 200

SELECT person_id, first_name, last_name FROM people WHERE first_name like :first_name or last_name like :last_name AND ((person_id > :_person_id)) ORDER BY person_id ASC LIMIT 2

我是执行这条sql 出现的这个问题。

SELECT * FROM people ;

person_id  first_name  last_name  
---------  ----------  ---------  
1          JOHN        DOE        
2          JOHN        DOE        
3          JOHN        DOE        
4          JOHN        DOE        
5          JOHN        DOE        
6          JOHN        DOE        
7          JOHN        DOE        
8          JOHN        DOE

SELECT person_id, first_name, last_name FROM people WHERE first_name like '%JOHN%' or last_name like '%DOE%' AND ((person_id > 2)) ORDER BY person_id ASC LIMIT 2

person_id  first_name  last_name  
---------  ----------  ---------  
1          JOHN        DOE        
2          JOHN        DOE

or的前一个条件总是成立,总是返回前两个记录,不管person_id 的大小。


AND 和 OR 运算符

AND 和 OR 可在 WHERE 子语句中把两个或多个条件结合起来。

如果第一个条件和第二个条件都成立,则 AND 运算符显示一条记录。

如果第一个条件和第二个条件中只要有一个成立,则 OR 运算符显示一条记录。

or 运算符 只要有一个为 true ,or 表达式为true ,则显示该记录。





### SQLiteOR 运算符的替代方案 在 SQLite 中,`OR` 运算符通常用于组合多个条件。然而,在某些情况下,特别是涉及索引优化时,`OR` 可能会降低性能,因为它可能阻止索引的有效利用[^3]。为了提高查询效率并实现功能上的等效操作,可以通过以下几种方式来替代 `OR`: #### 1. 使用 `UNION ALL` 通过将查询拆分为两个独立的部分,并使用 `UNION ALL` 将它们的结果集合并在一起,可以有效替代 `OR` 条件。这种方法允许每个子查询分别利用其自身的索引。 ```sql -- 原始查询 SELECT * FROM table_name WHERE condition1 OR condition2; -- 替代方案 SELECT * FROM table_name WHERE condition1 UNION ALL SELECT * FROM table_name WHERE condition2; ``` 注意:如果希望去重,则应使用 `UNION` 而不是 `UNION ALL`[^1]。 --- #### 2. 利用 `IN` 或者 `EXISTS` 当 `OR` 涉及到固定值列表或者子查询时,可以用 `IN` 或 `EXISTS` 来代替。这种方式不仅语义清晰,而且更容易被优化器处理。 ```sql -- 原始查询 SELECT * FROM people WHERE role = 'admin' OR role = 'manager'; -- 替代方案 SELECT * FROM people WHERE role IN ('admin', 'manager'); ``` 对于更复杂的场景,比如基于子查询的情况,也可以考虑使用 `EXISTS`: ```sql -- 原始查询 SELECT * FROM people p WHERE p.id = 1 OR EXISTS (SELECT 1 FROM roles r WHERE r.person_id = p.id); -- 替代方案 SELECT * FROM people p WHERE EXISTS ( SELECT 1 FROM dual WHERE p.id = 1 UNION ALL SELECT 1 FROM roles r WHERE r.person_id = p.id ); ``` 这里需要注意的是,`dual` 是一个虚拟表的概念,具体实现取决于数据库环境[^2]。 --- #### 3. 结合布尔逻辑重构表达式 有时可以通过重新排列布尔逻辑的方式减少对 `OR` 的依赖。例如,应用德摩根定律或其他逻辑变换技巧可以使查询更加高效。 假设原始查询如下: ```sql SELECT * FROM products WHERE price > 100 OR stock < 5; ``` 可以将其转换为: ```sql SELECT * FROM products WHERE NOT (price <= 100 AND stock >= 5); ``` 这种形式可能会使优化器更好地利用现有索引结构。 --- #### 4. 创建复合索引或调整查询策略 如果发现频繁使用的 `OR` 导致性能瓶颈,还可以尝试创建覆盖这些字段的复合索引。此外,手动指定查询计划(如通过 `CROSS JOIN` 控制连接顺序)也是一种可行的选择。 示例代码展示如何定义合适的索引来支持复杂条件匹配: ```sql CREATE INDEX idx_people_role_height ON people(role, height); ``` 随后可编写类似下面这样的查询以充分利用该索引: ```sql SELECT name FROM people WHERE role IN (SELECT DISTINCT role FROM people) AND height >= 180; ``` --- ### 总结 虽然直接替换掉所有的 `OR` 并不总是必要,但在特定条件下采用上述方法确实有助于提升查询性能以及改善索引利用率。最终选择哪种技术路线需视实际需求而定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值