SQL WHERE 条件查询

SQL WHERE是SQL的条件查询语句。SQL查询里的条件指定了要返回满足什么标准的信息。条件的值是TRUE或FALSE,从而限制查询中获取的数据。WHERE子句用于给查询添加条件,从而去除用户不需要的数据。WHERE自己本身比较简单,本文更多地介绍WHERE子句与比较运算符、逻辑运算符和通配符这三种方式对检索条件进行过滤。

WHERE子句里可以有多个条件,它们之间以操作符 ANDOR 连接。

SQL WHERE 语法

SELECT column_name,column_name
FROM table_name
WHERE column_name operator value;

SQL WHERE 子句比较运算符

在SQL中,我们可以使用WHERE子句对条件进行筛选,在此之前,你需要了解WHERE子句中的比较运算符。这些比较运算符的含义你可以参见下面这张表格:

SQL WHERE 条件查询

实际上你能看到,同样的含义可能会有多种表达方式,比如小于等于,可以是(<=),也可以是不大于(!>)。同样不等于,可以用(<>),也可以用(!=),它们的含义都是相同的,但这些符号的顺序都不能颠倒,比如你不能写(=<)。

需要注意的是,你需要查看使用的DBMS是否支持,不同的DBMS支持的运算符可能是不同的,比如Access不支持(!=),不等于应该使用(<>)。在MySQL中,不支持(!>)(!<)等。

极客教程在SQL 查询文章中使用了heros数据表,我们还是以这张表格做练习。下面我们通过比较运算符对王者荣耀的英雄属性进行条件筛选。

WHERE子句的基本格式是:SELECT ……(列名) FROM ……(表名) WHERE ……(子句条件)

比如我们想要查询所有最大生命值大于6000的英雄:

SELECT name, hp_max FROM heros WHERE hp_max > 6000

运行结果(41条记录):

SQL WHERE 条件查询

想要查询所有最大生命值在5399到6811之间的英雄:

SELECT name, hp_max FROM heros WHERE hp_max BETWEEN 5399 AND 6811

运行结果:(41条记录)

SQL WHERE 条件查询

需要注意的是hp_max可以取值到最小值和最大值,即5399和6811。

我们也可以对heros表中的hp_max字段进行空值检查。

SELECT name, hp_max FROM heros WHERE hp_max IS NULL

运行结果为空,说明heros表中的hp_max字段没有存在空值的数据行。

SQL WHERE 子句逻辑运算符

如果我们存在多个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_main和role_assist是OR(或)的关系。

第二部分是关于上线时间的条件过滤。NOT代表否,因为我们要找到不在2016-01-01到2017-01-01之间的日期,因此用到了NOT BETWEEN ‘2016-01-01’ AND ‘2017-01-01’。同时我们是在对日期类型数据进行检索,所以使用到了DATE函数,将字段birthdate转化为日期类型再进行比较。关于日期的操作,可以参考极客教程提供的。

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

SQL WHERE 条件查询

SQL WHERE 子句使用通配符进行过滤

刚才讲解的条件过滤都是对已知值进行的过滤,还有一种情况是我们要检索文本中包含某个词的所有数据,这里就需要使用通配符。通配符就是我们用来匹配值的一部分的特殊字符。这里我们需要使用到LIKE操作符。

如果我们想要匹配任意字符串出现的任意次数,需要使用(%)通配符。比如我们想要查找英雄名中包含“太”字的英雄都有哪些:

SELECT name FROM heros WHERE name LIKE '%太%'

运行结果:(2条记录)

SQL WHERE 条件查询

需要说明的是不同DBMS对通配符的定义不同,在Access中使用的是(*)而不是(%)。另外关于字符串的搜索可能是需要区分大小写的,比如'liu%'就不能匹配上'LIU BEI'。具体是否区分大小写还需要考虑不同的DBMS以及它们的配置。

如果我们想要匹配单个字符,就需要使用下划线(_)通配符。(%)和(_)的区别在于

  • %)代表一个或多个字符
  • _)只代表一个字符

比如我们想要查找英雄名除了第一个字以外,包含“太”字的英雄有哪些。

SELECT name FROM heros WHERE name LIKE '_%太%'

运行结果(1条记录):

SQL WHERE 条件查询

因为太乙真人的太是第一个字符,而_%太%中的太不是在第一个字符,所以匹配不到“太乙真人”,只可以匹配上“东皇太一”。

同样需要说明的是,在Access中使用(?)来代替(_),而且在DB2中是不支持通配符(_)的,因此你需要在使用的时候查阅相关的DBMS文档。

你能看出来通配符还是很有用的,尤其是在进行字符串匹配的时候。不过在实际操作过程中,我还是建议你尽量少用通配符,因为它需要消耗数据库更长的时间来进行匹配。即使你对LIKE检索的字段进行了索引,索引的价值也可能会失效。如果要让索引生效,那么LIKE后面就不能以(%)开头,比如使用LIKE '%太%'LIKE '%太'的时候就会对全表进行扫描。如果使用LIKE '太%',同时检索的字段进行了索引的时候,则不会进行全表扫描。

关于SQL 查询,请参与极客教程提供的SQL 教程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程