ITPub博客

首页 > 数据库 > 数据库开发技术 > 《PostgreSQL 开发指南》第 10 篇 查询条件

《PostgreSQL 开发指南》第 10 篇 查询条件

原创 数据库开发技术 作者:BUAA_dxy 时间:2022-02-21 20:33:05 0 删除 编辑

在上一篇中,我们介绍了如何使用SELECT和FROM关键字查询表中的全部数据。如果只想返回满足某些条件的数据,比如某个部门或者某些职位的员工、姓名以特定字符串开头的员工等,需要使用 SQL 中的WHERE子句。

WHERE 子句

WHERE子句的语法如下:

SELECT column1, column2, ... 
FROM table
WHERE conditions;

WHERE子句位于FROM之后,用于指定一个或者多个逻辑条件,用于过滤返回的结果。满足条件的行将会返回,否则将被忽略。PostgreSQL 提供了各种运算符和函数,用于构造逻辑条件。

先看一个简单的示例,以下语句返回薪水为 10000 的员工。

SELECT first_name,
last_name,
salary
FROM employees
WHERE salary = 10000;
first_name | last_name | salary
------------+-----------+----------
Peter | Tucker | 10000.00
Janette | King | 10000.00
Harrison | Bloom | 10000.00
Hermann | Baer | 10000.00
(4 rows)

此处的等于号(=)是一个比较运算符,因此只有薪水等于 10000 的数据应用该运算符之后的结果为真值(True),返回结果中只包含这些数据。

PostgreSQL 提供了以下各种比较运算符。

运算符 描述 示例
= 等于 manager_id = 100
!= 不等于 department_id != 50
<> 不等于 job_id <> ‘SA_REP’
> 大于 salary > 10000
>= 大于等于 hire_date >= ‘2007-01-01’
< 小于 salary < 15000
<= 小于等于 employee_id <= 123
BETWEEN 位于范围之内 salary BETWEEN 10000 AND 15000
IN 属于列表之中 job_id IN (‘AC_MGR’, ‘HR_REP’, ‘IT_PROG’)

以上这些运算符的作用都比较明显,不做详细介绍。需要注意的是BETWEEN包含了两端的值,等价于>=加上<=。

SELECT first_name,
last_name,
salary
FROM employees
WHERE salary BETWEEN 11000 AND 12000;
first_name | last_name | salary
------------+-----------+----------
Den | Raphaely | 11000.00
Alberto | Errazuriz | 12000.00
Gerald | Cambrault | 11000.00
Lisa | Ozer | 11500.00
Ellen | Abel | 11000.00
(5 rows)

模式匹配

PostgreSQL 支持各种字符串模式匹配的功能。最简单的方式就是使用LIKE运算符,以下查询返回姓氏(last_name)以“Kin”开头的员工。

SELECT first_name,
last_name
FROM employees
WHERE last_name LIKE 'Kin%';
first_name | last_name
------------+-----------
Steven | King
Janette | King
(2 rows)

其中的百分号(%)可以匹配零个或者多个任意字符;另外,下划线(_)可以匹配一个任意字符。例如:

  • “%en”匹配以“en”结束的字符串;

  • “%en%”匹配包含“en”的字符串;

  • “B_g”匹配“Big”、“Bug”等。

如果字符串中存在这两个通配符(% 或 _),可以在它们前面加上一个反斜杠(\)进行转义。
SELECT 1 WHERE 'this is 25%' LIKE '%25\%';
?column?
----------
1
(1 row)

也可以通过ESCAPE子句指定其他的转义字符。

SELECT 1 WHERE 'this is 25%' LIKE '%25@%' ESCAPE '@';
?column?
----------
1
(1 row)

另外,NOT LIKE运算符匹配与LIKE相反的结果。

SELECT first_name,
last_name
FROM employees
WHERE last_name NOT LIKE 'Kin%';
first_name | last_name
-------------+-------------
Neena | Kochhar
Lex | De Haan
Nancy | Greenberg
Daniel | Faviet
John | Chen
......
(105 rows)

LIKE运算符区分大小写,PostgreSQL 同时还提供了不区分大小写的ILIKE运算符。

SELECT first_name,
last_name
FROM employees
WHERE last_name LIKE 'kin%';
first_name | last_name
------------+-----------
(0 rows)

SELECT first_name,
last_name
FROM employees
WHERE last_name ILIKE 'kin%';
first_name | last_name
------------+-----------
Steven | King
Janette | King
(2 rows)

PostgreSQL 还提供了更加复杂的正则表达式匹配等功能,详细内容可以参考官方文档。

空值判断

根据 SQL 标准,空值使用NULL表示。它是一个特殊值,代表了未知数据。如果使用常规的比较运算符与NULL进行比较,总是返回空值。

NULL = 0; -- 结果为空值
NULL = NULL; -- 结果为空值
NULL != NULL; -- 结果为空值

如果在查询条件中使用这种方式,将不会返回任何结果。因此,对于NULL值的比较,需要使用特殊的运算符:IS NULL。

SELECT first_name,
last_name,
department_id
FROM employees
WHERE department_id IS NULL;
first_name | last_name | department_id
------------+-----------+---------------
Kimberely | Grant |
(1 row)

以上查询返回了部门编号为空的员工,意味着他还没有分配到任何部门。

IS NOT NULL执行与IS NULL相反的操作,返回值不为空的数据。

复杂条件

WHERE子句可以包含多个条件,使用逻辑运算符(AND、OR、NOT)将它们进行组合,并根据最终的逻辑值进行过滤。

AND逻辑与运算符的逻辑真值表如下:

  TRUE FALSE NULL
TRUE TRUE FALSE NULL
FALSE FALSE FALSE FALSE
NULL NULL FALSE NULL

对于AND运算符,只有当它两边的结果都为真时,最终结果才为真;否则最终结果为假,不返回结果。以下查询返回薪水为 10000,并且姓氏为“King”的员工:

SELECT first_name,
last_name,
salary
FROM employees
WHERE salary = 10000 AND last_name = 'King';
first_name | last_name | salary
------------+-----------+----------
Janette | King | 10000.00
(1 row)

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

  TRUE FALSE NULL
TRUE TRUE TRUE TRUE
FALSE TRUE FALSE NULL
NULL TRUE NULL NULL

OR逻辑或运算符只要有一个条件为真,结果就为真。以下查询返回薪水为 10000,或者姓氏为“King”的员工:

SELECT first_name,
last_name,
salary
FROM employees
WHERE salary = 10000 OR last_name = 'King';
first_name | last_name | salary
------------+-----------+----------
Steven | King | 24000.00
Peter | Tucker | 10000.00
Janette | King | 10000.00
Harrison | Bloom | 10000.00
Hermann | Baer | 10000.00
(5 rows)

对于逻辑运算符AND和OR,需要注意的是,它们使用短路运算。也就是说,只要前面的表达式能够决定最终的结果,不进行后面的计算。这样能够提高运算效率。因此,以下语句不会产生除零错误:

SELECT 1 WHERE 1 = 0 AND 1/0 = 1;
SELECT 1 WHERE 1 = 1 OR 1/0 = 1;

还需要注意的一个问题是,当我们组合AND和OR运算符时,AND运算符优先级更高,总是先执行。

SELECT first_name,
last_name,
salary
FROM employees
WHERE salary = 10000 OR salary = 24000 AND last_name = 'King';
first_name | last_name | salary
------------+-----------+----------
Steven | King | 24000.00
Peter | Tucker | 10000.00
Janette | King | 10000.00
Harrison | Bloom | 10000.00
Hermann | Baer | 10000.00
(5 rows)

由于AND优先级高,查询返回的是薪水为 24000 并且姓氏为“King”的员工,或者薪水为 10000 的员工。如果相要返回姓氏为“King”,并且薪水为 10000 或 24000 的员工,可以使用括号修改优先级:

SELECT first_name,
last_name,
salary
FROM employees
WHERE (salary = 10000 OR salary = 24000)
AND last_name = 'King';
first_name | last_name | salary
------------+-----------+----------
Steven | King | 24000.00
Janette | King | 10000.00
(2 rows)

NOT运算符用于取反操作,它的逻辑真值表如下:

  NOT
TRUE FALSE
FALSE TRUE
NULL NULL

注意,对于未知的NULL值,经过NOT处理之后仍然是未知值。

除此之外,NOT还可以结合前面介绍的运算符一起使用:

  • NOT BETWEEN,位于范围之外

  • NOT IN,不在列表之中

  • NOT LIKE,不匹配模式

  • NOT IS NULL,不为空,等价于IS NOT NULL

最后,当查询条件包含复杂逻辑时,它们的运算优先级从高到低排列如下:
条件运算符 描述
=, !=, <>, <, <=, >, >= 比较运算

IS [NOT] NULL

[NOT] LIKE

[NOT] BETWEEN

[NOT] IN

[NOT] EXISTS

比较运算
NOT 逻辑否定
AND 逻辑与
OR 逻辑或

使用括号可以调整多个运算符之间的优先级。

原文作者:SQL编程思想;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论
《SQL编程思想》作者,专注于数据库领域知识的分享。

注册时间:2021-08-26

  • 博文量
    443
  • 访问量
    546977