DuckDB教程:构造复杂过滤条件

如果只能使用单个过滤条件,SQL 语句就无法满足复杂的查询需求,例如查找月薪超过 10000 的女性员工。

为此,SQL借助于逻辑代数中的运算提供了三个逻辑运算符,可以基于多个运算符构建复杂的过滤条件。

逻辑与(AND)运算符

对于逻辑与运算符,只有当运算符两边的条件都为真时才返回数据,否则查询不返回数据。例如,以下语句使用 AND 运算符查找月薪超过 10000 的女性员工:

sql 复制代码
SELECT emp_name, sex, salary
FROM employee
WHERE sex = '女'
AND salary > 10000;

┌──────────┬─────────┬──────────────┐
│ emp_name │   sex   │    salary    │
│ varchar  │ varchar │ decimal(8,2) │
├──────────┼─────────┼──────────────┤
│ 孙尚香   │ 女      │     12000.00 │
└──────────┴─────────┴──────────────┘

女性员工中只有"孙尚香"的月薪超过了10000。

SQL中逻辑运算的结果存在三种情况:真、假或者未知(Unknown)。逻辑与(AND)运算符的真值表如下:

a b a AND b
true true true
true false false
true NULL NULL
false false false
false NULL false
NULL NULL NULL

逻辑或(OR)运算符

对于逻辑或运算符,只要运算符两边的条件有一个为真就返回数据,否则查询不返回数据。例如,我们可以使用 OR 运算符查找姓名为"刘备"、"关羽"或者"张飞"的员工:

sql 复制代码
SELECT emp_id, emp_name
FROM employee
WHERE emp_name = '刘备' OR emp_name = '关羽' OR emp_name = '张飞';

┌────────┬──────────┐
│ emp_id │ emp_name │
│ int32  │ varchar  │
├────────┼──────────┤
│      1 │ 刘备     │
│      2 │ 关羽     │
│      3 │ 张飞     │
└────────┴──────────┘

逻辑或(OR)运算符的真值表如下:

a b a OR b
true true true
true false true
true NULL true
false false false
false NULL NULL
NULL NULL NULL

短路运算

对于逻辑运算符 AND 和 OR,SQL 使用短路运算(Short-Circuit Evaluation)。也就是说,只要左边的表达式能够决定最终的结果就不计算右边的表达式。

例如:

sql 复制代码
SELECT 1=0 AND 1/'a';
 
┌─────────────────────────┐
│ ((1 = 0) AND (1 / 'a')) │
│         boolean         │
├─────────────────────────┤
│ false                   │
└─────────────────────────┘

SELECT 1/'a' AND 1=0;
Conversion Error:
Could not convert string 'a' to DOUBLE

LINE 1: SELECT 1/'a' AND 1=0;
                 ^

第一个查询使用了 AND 运算符,由于 1=0 结果为假,查询结果肯定为假,不需要计算右边的 1/'a'。

第二个查询先执行左边的 1/'a',出现类型转换错误。

提示:短路运算方法可以减少某些情况下的表达式计算,提高运算的效率。

逻辑非(NOT)运算符

逻辑非运算符与其他运算符一起使用时表示将随后的运算结果取反知:

  • NOT >,查找不大于(小于等于)指定值的数据。也可以使用NOT=、NOT<等运算符。
  • NOT BETWEEN,查找位于指定范围之外的数据。
  • NOT IN,查找不在指定列表之中的数据。
  • NOT LIKE,查找不匹配某个模式的文本。
  • NOT expr IS NULL,查找 expr 不为空的数据,等价于 expr IS NOT NULL。

例如,以下语句查找奖金小于 2000 或者大于 10000 的员工:

sql 复制代码
SELECT emp_name, bonus
FROM employee
WHERE NOT bonus BETWEEN 2000 AND 10000;

┌──────────┬──────────────┐
│ emp_name │    bonus     │
│ varchar  │ decimal(8,2) │
├──────────┼──────────────┤
│ 蒋琬     │      1500.00 │
└──────────┴──────────────┘

虽然有很多员工没有奖金(bonus字段为空),但是查询并没有返回这些员工的信息,因为未知结果取反之后仍然未知。

运算符优先级

我们还需要注意多个运算符之间的优先级问题。一般来说,比较运算符的优先级比逻辑运算符更高,逻辑运算符中 NOT 比 AND 优先级高,AND 比 OR 优先级高。

通常优先级高的运算符先执行,相同级别的运算符从左至右执行。

假如我们想要知道人力资源部(dept_id=2)或者财务部(dept_id=3)中有哪些员工拥有奖金,如果使用以下查询语句:

sql 复制代码
SELECT emp_name, dept_id, bonus
FROM employee
WHERE dept_id = 2 OR dept_id = 3
AND bonus IS NOT NULL;

┌──────────┬─────────┬──────────────┐
│ emp_name │ dept_id │    bonus     │
│ varchar  │  int32  │ decimal(8,2) │
├──────────┼─────────┼──────────────┤
│ 诸葛亮   │       2 │      8000.00 │
│ 黄忠     │       2 │         NULL │
│ 魏延     │       2 │         NULL │
│ 孙尚香   │       3 │      5000.00 │
└──────────┴─────────┴──────────────┘

查询结果中,"黄忠"和"魏延"并没有奖金,不是我们期望的结果。那么问题出在哪里了呢?

因为 AND 运算符比 OR 运算符的优先级高,以上查询实际返回了人力资源部(dept_id=2)的员工,以及财务部(dept_id=3)中拥有奖金的员工。

如果想要获得我们期望的结果,可以使用圆括号调整运算符的优先级,例如:

sql 复制代码
SELECT emp_name, dept_id, bonus
FROM employee
WHERE (dept_id = 2 OR dept_id = 3) AND bonus IS NOT NULL;

┌──────────┬─────────┬──────────────┐
│ emp_name │ dept_id │    bonus     │
│ varchar  │  int32  │ decimal(8,2) │
├──────────┼─────────┼──────────────┤
│ 诸葛亮   │       2 │      8000.00 │
│ 孙尚香   │       3 │      5000.00 │
└──────────┴─────────┴──────────────┘
相关推荐
l1t6 天前
用李红艳先生的DuckDB luajit插件批量计算数独
数据库·sql·lua·duckdb
johnny23314 天前
DuckDB简介与、生态、实战:MotherDuck、Duckle、SQLFlow、DuckQuery
duckdb
不剪发的Tony老师22 天前
DuckDB直接连接MySQL,以后还需要ETL吗?
mysql·数据分析·etl·duckdb
不剪发的Tony老师1 个月前
DuckDB数据分析实战:CSV文件导入导出
数据分析·csv·duckdb
l1t1 个月前
在linux和windows中解决duckdb 1.6dev版本输出执行计划报错问题
linux·运维·数据库·windows·duckdb
l1t2 个月前
DuckDB对group by cube / rollup / groupping sets查询的优化
数据库·duckdb
l1t2 个月前
DeepSeek总结的DuckDB-Iceberg 在 v1.5.3 中的新特性
数据库·duckdb
DarkAthena3 个月前
【DuckDB】一条 SQL 同时连接 Oracle 和 GaussDB
oracle·gaussdb·duckdb
l1t3 个月前
DeepSeek总结的在 DuckDB 中试驾 Lance 数据湖仓格式
数据库·人工智能·机器学习·duckdb