SQL WHERE条件查询

SQL 基本查询语句我们介绍了基本的查询语句,学习了如何使用 SELECT 和 FROM 查询表中的数据。

但在实际应用中通常并不需要返回表中的全部数据,而只需要找出满足某些条件的结果。比如,某个部门中的员工或者某个产品最近几天的销售情况。在 SQL 中,可以通过查询条件实现数据的过滤。

SQL 语句中,使用关键字 WHERE 指定查询的过滤条件。以下语句只返回姓名为“刘备”的员工信息:

SELECT *
  FROM employee
 WHERE emp_name = '刘备';

其中,WHERE 位于 FROM 之后,用于指定一个或者多个过滤条件;只有满足条件的数据才会返回,其他数据将被忽略。该语句执行的结果如下:

SQL WHERE条件查询

在 SQL 中,WHERE 子句也被称为谓词(Predicate)。

这种通过查询条件过滤数据的操作在关系运算中被称为选择(Selection)。

在查询条件中,使用最多的就是数据的比较运算。

SQL 条件查询中使用比较运算符

比较运算符可以比较两个数值的大小,包括字符、数字以及日期类型的数据。下表列出了 SQL 中的各种比较运算符:

运算符 描述 示例
= 等于 WHERE emp_id = 1
!= 或者 <> 不等于 WHERE sex != '男'
> 大于 WHERE salary > 10000
>= 大于等于 WHERE hire_date >= DATE '2018-01-01'
< 小于 WHERE bonus < 15000
<= 小于等于 WHERE dept_id <= 2
BETWEEN 位于范围之内 WHERE salary BETWEEN 10000 AND 15000
IN 属于列表之中 WHERE emp_name IN ('刘备', '关羽', '张飞')

Oracle 中 ^= 运算符也表示不等于。

这些运算符的作用都比较好理解。我们来看一个日期数据的比较操作,假设想要知道哪些员工在 2018 年 1 月 1 日之后入职,可以使用以下查询:

-- 适用于 Oracle、MySQL 以及 PostgreSQL
SELECT emp_name, hire_date
  FROM employee
 WHERE hire_date >= DATE '2018-01-01';

其中,DATE '2018-01-01'定义了一个日期类型的常量值。对于 SQL Server,指定日期时可以直接使用字符串字面值表示:

-- 适用于 SQL Server、MySQL 以及 PostgreSQL
SELECT emp_name, hire_date
  FROM employee
 WHERE hire_date >= '2018-01-01';

以上两个查询语句的结果如下:

SQL WHERE条件查询

除了我们常见的比较运算符之外,SQL 还提供了两个特殊的比较运算符:BETWEEN 和 IN。

BETWEEN 运算符

如果想要查找一个范围内的数据,可以使用 BETWEEN 运算符。以下示例查询月薪位于 10000 到 15000 之间的员工:

SELECT emp_name, salary
  FROM employee
 WHERE salary BETWEEN 10000 AND 15000;

该语句的结果如下:

SQL WHERE条件查询

需要注意的是,BETWEEN 包含了两端的值(10000 和 15000)。

IN 运算符

IN 运算符可以用于查找列表中的值。以下示例查询姓名为“刘备”、“关羽”或者“张飞”的员工:

SELECT emp_id, emp_name
  FROM employee
 WHERE emp_name IN ('刘备', '关羽', '张飞');

该查询的结果如下:

SQL WHERE条件查询

只要匹配列表中的任何一个值,都会返回结果。IN 运算符还有一个常见的用途就是子查询的结果匹配。

SQL 条件查询中使用逻辑运算符

刚才介绍了比较运算符,如果我们存在多个WHERE条件子句,可以使用逻辑运算符:

SQL WHERE条件查询

我们还是通过例子来看下这些逻辑运算符的使用,同样采用heros这张表的数据查询。

假设想要筛选最大生命值大于6000,最大法力大于1700的英雄,然后按照最大生命值和最大法力值之和从高到低进行排序。

SELECT name, hp_max, mp_max FROM heros WHERE hp_max > 6000 AND mp_max > 1700 ORDER BY (hp_max+mp_max) DESC

运行结果:(23条记录)

SQL WHERE条件查询

如果AND和OR同时存在WHERE子句中会是怎样的呢?假设我们想要查询最大生命值加最大法力值大于8000的英雄,或者最大生命值大于6000并且最大法力值大于1700的英雄。

SELECT name, hp_max, mp_max FROM heros WHERE (hp_max+mp_max) > 8000 OR hp_max > 6000 AND mp_max > 1700 ORDER BY (hp_max+mp_max) DESC

运行结果:(33条记录)

SQL WHERE条件查询

你能看出来相比于上一个条件查询,这次的条件查询多出来了10个英雄,这是因为我们放宽了条件,允许最大生命值+最大法力值大于8000的英雄显示出来。另外你需要注意到,当WHERE子句中同时存在OR和AND的时候,AND执行的优先级会更高,也就是说SQL会优先处理AND操作符,然后再处理OR操作符。

如果我们对这条查询语句OR两边的条件增加一个括号,结果会是怎样的呢?

SELECT name, hp_max, mp_max FROM heros WHERE ((hp_max+mp_max) > 8000 OR hp_max > 6000) AND mp_max > 1700 ORDER BY (hp_max+mp_max) DESC

运行结果:

SQL WHERE条件查询

所以当WHERE子句中同时出现AND和OR操作符的时候,你需要考虑到执行的先后顺序,也就是两个操作符执行的优先级。一般来说()优先级最高,其次优先级是AND,然后是OR。

如果我想要查询主要定位或者次要定位是法师或是射手的英雄,同时英雄的上线时间不在2016-01-01到2017-01-01之间。

SELECT name, role_main, role_assist, hp_max, mp_max, birthdate
FROM heros 
WHERE (role_main IN ('法师', '射手') OR role_assist IN ('法师', '射手')) 
AND DATE(birthdate) NOT BETWEEN '2016-01-01' AND '2017-01-01'
ORDER BY (hp_max + mp_max) DESC

你能看到我把WHERE子句分成了两个部分。第一部分是关于主要定位和次要定位的条件过滤,使用的是role_main in ('法师', '射手') OR role_assist in ('法师', '射手')。这里用到了IN逻辑运算符,同时role_mainrole_assist是OR(或)的关系。

第二部分是关于上线时间的条件过滤。NOT代表否,因为我们要找到不在2016-01-01到2017-01-01之间的日期,因此用到了NOT BETWEEN '2016-01-01' AND '2017-01-01'。同时我们是在对日期类型数据进行检索,所以使用到了DATE函数,将字段birthdate转化为日期类型再进行比较。关于日期的操作,我会在下一篇文章中再作具体介绍。

这是运行结果(6条记录):

SQL WHERE条件查询

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程