Mysql教程

10.2单表查询

单表查询是指从一张表中查询所需要的数据。查询数据时,可以从一张表中查询数据,也可以从多张表中同时查询数据。两者的查询方式上有一定的区别。因为单表查询只在一 张表上进行操作,所以查询比较简单。本小节将讲解在单表上查询所有的字段、查询指定 的字段、查询指定的行、多条件查询、查询结果不重复、给查询结果排序、分组查询和用 LIMIT限制查询结果的数量等内容。

10.2.1查询所有字段

查询所有字段是指査询表中所有字段的数据。这种方式可以将表中所有字段的数据都查询出来。MySQL中有两种方式可以査询表中所有的字段。本小节将详细讲解这两种方法。

1.列出表的所有字段

MySQL中,可以在SELECT语句的“属性列表”中列出所要查询的表中的所有的字段。下文中用一个例子来详细说明这种方法。

【示例10-3】下面用SELECT语句査询employee表中的所有字段的数据。在执行SELECT语句之前,可以先看一下Eemployee表中的所有记录。

+-------+--------+-------+-------+-------+----------------+
|  num  |  d_id  | name  |  age  |  sex  |    homeaddr    |
+-------+--------+-------+-------+-------+----------------+
|    1  |  1001  | 张三  |   26  |   男  |  北京市海淀区  |
|    2  |  1002  | 李四  |   24  |   女  |  北京市昌平区  |
|    3  |  1003  | 王五  |   25  |   男  |  湖南省长沙市  |
|    4  |  1004  | Aric  |   15  |   男  |  England       |
+-------+--------+-------+-------+-------+----------------+
4 rows in set(0.00 sec)

上面可以看到,employee表中包含6个字段,分别是num、d_id、name、age、sex、homeaddr。下面是要查询employee表的所有字段的SELECT语句:

SELECT num,d_id,name,age,sex,homeaddr FROM employee;
mysql>SELECT num,d_id,name,age,sex,homeaddr FROM employee;
+-------+--------+-------+-------+-------+----------------+
|  num  |  d_id  | name  |  age  |  sex  |    homeaddr    |
+-------+--------+-------+-------+-------+----------------+
|    1  |  1001  | 张三  |   26  |   男  |  北京市海淀区  |
|    2  |  1002  | 李四  |   24  |   女  |  北京市昌平区  |
|    3  |  1003  | 王五  |   25  |   男  |  湖南省长沙市  |
|    4  |  1004  | Aric  |   15  |   男  |  England       |
+-------+--------+-------+-------+-------+----------------+
4 rows in set(0.00 sec)

查询结果显示,已经成功查询了employee表的所有字段的数据。这个方式比较灵活,可以改变字段显示的顺序。例如,可以将d_id字段显示为最后一列。代码执行如下:

mysql>SELECT num,name,age,sex,homeaddr,d_id FROM employee;
+-------+--------+-------+-------+-------+----------------+
|  num  |  name  |  age  |  sex  |    homeaddr    | d_id  |
+-------+--------+-------+-------+-------+----------------+
|    1  |  张三  |   26  |   男  |  北京市海淀区  | 1001  |
|    2  |  李四  |   24  |   女  |  北京市昌平区  | 1002  |
|    3  |  王五  |   25  |   男  |  湖南省长沙市  | 1003  |
|    4  |  Aric  |   15  |   男  |  England      | 1004  |
+-------+--------+-------+-------+-------+----------------+
4 rows in set(0.00 sec)

结果显示,d_id字段已经被放在最后一列显示。

使用"*"查询所有字段

在MySQL中,SELECT语句的“属性列表”中可以为“*”。其基本语法形式为: SELECT * FROM 表名; “*”可以表示所有的字段。这样就不用列出表中所有字段的名称了。但是,使用这种方式查询时,只能按照表中字段的顺序进行排列,不能改变字段的排列顺序。

【示例10-4】下面用SELECT语句来查询employee表的所有字段的数据,此处用“*” 来代替“属性列表”。SELECT语句的代码如下:

SELECT * FROM employee;

代码执行如下:

mysql> select * from employee;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
4 rows in set (0.00 sec)

这种方式同样也查询出了表中所有字段的数据。这种方式比较方便,但是显示的结果不够灵活。

技巧:虽然列出表的所有字段的方式比较灵活,但是查询所有字段时通常使用“SELECT *FROM表名”。使用这种方式比较简单。尤其是表中的字段很多的时候,这种方式的优势就更加明显。当然,如果需要改变字段显示的顺序,就选择列表的所有字段。

10.2.2查询指定字段

查询数据时,可以在SELECT语句的“属性列表”中列出所要查询的字段。这种方式可以指定需要查询的字段,而不需要查询出所有的字段。

【示例10-5】下面查询employee表中num、name、sex和homeaddr等4个字段的数据。SELECT语句的代码如下。

select num,name,sex,homeaddr FROM employee;
mysql> SELECT num, name, homeaddr,sex FROM employee;
+-----+------+--------------+-----+
| num | name | homeaddr     | sex |
+-----+------+--------------+-----+
|   1 | 张三     | 北京市海淀区            | 男    |
|   2 | 李四     | 北京市昌平区           | 女   |
|   3 | 王五     | 湖南省长沙市           | 男    |
|   4 | Aric | England      | 男    |
+-----+------+--------------+-----+
4 rows in set (0.00 sec)

结果显示了 num、name、sex和homeaddr等4个字段的数据。结果中字段的排列顺序 与SELECT语句中字段的排列顺序相同。如果改变SELECT语句中字段的排列顺序,可以改变结果中字段的显示顺序。例如,将homeaddr字段排到sex字段前面,其代码执行如下:

SELECT num, name, homeaddr,sex FROM employee;
mysql> SELECT num, name, homeaddr,sex FROM employee;
+-----+------+--------------+-----+
| num | name | homeaddr     | sex |
+-----+------+--------------+-----+
|   1 | 张三     | 北京市海淀区            | 男    |
|   2 | 李四     | 北京市昌平区           | 女   |
|   3 | 王五     | 湖南省长沙市           | 男    |
|   4 | Aric | England      | 男    |
+-----+------+--------------+-----+
4 rows in set (0.00 sec)

结果显示,homeaddr字段和seX字段的顺序发生了变化。这一特性可以让用户根据自己的需要来显示查询结果。

注意:查询的字段必须包含在表中。如果查询的字段不在表中,系统会报错。例如,在employee表中查询money字段,系统会出现“ERROR 1054 (42S22): Unknown column 'money' in Tield list’”这样的错误提示信息。

10.2.3查询指定记录

SELECT语句中可以设置查询条件。用户可以根据自己的需要来设置査询条件,按条件进行查询。查询的结果必须满足査询条件。例如,用户需要查找d_id为1001的记录,那么可以设置“d_id=1001”为査询条件。这样査询结果中的记录就都会满足“d_id=1001” 这个条件。WHERE子句可以用来指定查询条件。其语法规则如下:

WHERE条件表达式

其中,“条件表达式”参数指定SELECT语句的查询条件。

【示例10-6】下面査询employee表中d_id为1001的记录。SELECT语句的代码如下:

SELECT * FROM employee WHERE d_id=1001;
mysql> SELECT * FROM employee WHERE d_id=1001;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
+-----+------+------+-----+-----+--------------+
1 row in set (0.00 sec)

查询结果中只包含d_id为1001的记录。如果根据指定的条件进行査询时,没有查出 任何结果,系统会提示"Empty set (0.00sec)"

【示例10-7】下面査询employee表中d_id.=1005的记录。代码执行如下:

SELECT * FROM employee WHERE d_id=1005;
Empty set (0.00sec)


因为,employee表中没有满足"d_id=1005"的记录,所以结果显示"Empty set".

WHERE自居常用的查询条件有很多种,如下表所示。

查询条件 符号或关键字
比较 =,<,<=,>,>=,!=,<>,!>,!<
指定范围 BETWEEN AND,NOT BETWEEN AND
指定集合 IN,NOTIN
匹配字符 LIKE,NOTLIKE
是否为空值 IS NULL, IS NOT NULL
多个查询条件 AND,OR

表中,"<>"表示不等于,其作用等价于"!="; "!>"表示不大于,等价于"<="; "!<"表示不小于,等价于">=";BETWEEN AND指定了某字段的取值范围; "IN"指定了某字段的取值的集合;IS NULL用来判断某字段的取值是否为空; AND和OR用来连接多个查询条件。关于这些查询条件的内容,后面的章节中会详细地介绍。下一个小节将 介绍"IN"关键字在查询数据时的使用。

注意:条件表达式中设置的条件越多,查询出来的记录就会越少。因为,设置的条件越多,查询语句的限制就更多,能够满足所有条件的记录就更少。为了使查询出来的记录正是自己想要查询的记录,可以在WHERE语句中将查询条件设置得更加具体。

10.2.4带IN关键字的查询

IN关键字可以判断某个字段的值是否在指定的集合中。如果字段的值在集合中,则满足查询条件,该记录将被查询出来;如果不在集合中,则不满足查询条件。其语法规则如下:

[NOT] IN (元素1,元素2,...,元素n)

其中,"NOT"是可选参数,加上NOT表示不在集合内满足条件;"元素n"表示集合中的元素,各元素之间用逗号隔开,字符型元素需要加上单引号。

【示例10-8】下面使用IN关键字进行査询。SELECT语句的代码如下:

SELECT  * FROM employee WHERE d_id IN ( 1001, 1004 );
mysql> SELECT  * FROM employee WHERE d_id IN ( 1001, 1004 );
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
2 rows in set (0.00 sec)

结果显示,d_id字段的取值为1001或1004的记录都被查询出来。如果集合中的元素为字符时,须加单引号。

【示例10-9】下面使用NOT IN关键字进行查询,而且集合的元素为字符型数据。 SELECT语句的代码如下:

SELECT *FROM employee WHERE name NOT IN('张三','李四');
mysql> SELECT *FROM employee WHERE name NOT IN('张三','李四');
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
2 rows in set (0.01 sec)

结果显示,name字段的取值为“张三”和“李四”的记录都被排除掉了。通过这两个例子,读者可以清楚的了解到IN关键字的语句和用处。

10.2.5 带BETWEEN AND的范围查询

BETWEEN AND关键字可以判读某个字段的值是否在指定的范围内。如果字段的值在指定范围内,则满足查询条件,该记录将被查询出来。如果不在指定范围内,则不满足査询条件。其语法规则如下:

[NOT]BETWEEN 取值1 AND 取值2

其中,“NOT”是可选参数,加上NOT表示不在指定范围内满足条件;“取值丨”表示范围的起始值;“取值2”表示范围的终止值。

【示例10-10】下面使用BETWEEN AND关键字进行査询,査询条件是age字段的取 值从15~25。SELECT语句的代码如下:

SELECT * FROM employee WHERE age BETWEEN 15 AND 25 ;

代码执行如下:

mysql> SELECT * FROM employee WHERE age BETWEEN 15 AND 25 ;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
3 rows in set (0.00 sec)
\

结果显示,age字段的取值是大于等于15,且小于等于25。由此可以知道,BETWEEN AND的范围是大于等于“取值1”,而小于等于“取值2”的。 NOT BETWEENAND的取值范围是小于“取值1”,而大于“取值2”。

【示例10-11】下面使用NOT BETWEEN AND关键字查询employee表。查询条件是 age字段的取值不在15〜25之间。SELECT语句的代码如下:

SELECT * FROM employee WHERE age NOT BETWEEN 15 AND 25 ;

代码执行如下:

mysql> SELECT * FROM employee WHERE age NOT BETWEEN 15 AND 25 ;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
+-----+------+------+-----+-----+--------------+
1 row in set (0.00 sec)

结果显示,只有age等于26的记录满足条件。可以看出NOT BETWEENAND的取值是小于15,或大于25。

技巧:BETWEEN AND和NOT BETWEEN AND关键字在查询指定范围的记录时很有用。例如,查询学生表的年龄段、分数段等。还有查询员工的工资水平时也可以使用这两个关键字。

10.2.6带LIKE的字符匹配查询

LIKE关键字可以匹配字符串是否相等。如果字段的值与指定的字符串相匹配,则满足查询条件,该记录将被查询出来。如果与指定的字符串不匹配,则不满足查询条件。其 语法规则如下:

[NOT] LIKE '字符串'

其中,"NOT"是可选参数,加上NOT表示与指定的字符串不匹配时满足条件;“字符串”表示指定用来匹配的字符串,该字符串必须加单引号或者双引号。“字符串”参数 的值可以是一个完整的字符串,也可以是包含百分号(%)或者下划线(_)的通配字符。 但是%和_有很大的差別:

  • “%”可以代表任意长度的字符串,长度可以为0。例如,b%k处表示以字母b开头, 以k母让结尾的任意长度的字符串。该字符串内以代表bk、buk、book、break、 bedrock等字符串。

  • “_”只能表示单个字符。例如,b_k表示以字母b开头,以字母k结尾的3个字符。 中间的“_”可以代表任意一个字符。字符串可以代表bok bak和buk等字符串。

【示例10-12】下面使用LIKE关键字来匹配一个完整的字符串‘AriC’。SELECT语句的代码如下:

SELECT * FROM employee WHERE name LIKE 'Aric';
mysql> SELECT * FROM employee WHERE name LIKE 'Aric';
+-----+------+------+-----+-----+----------+
| num | d_id | name | age | sex | homeaddr |
+-----+------+------+-----+-----+----------+
|   4 | 1004 | Aric |  15 | 男    | England  |
+-----+------+------+-----+-----+----------+
1 row in set (0.00 sec)

结果显示,查询出name字段的取值是Aric的记录。其他不满足条件的记录都被忽略掉了。此处的LIKE与等于号(=)是等价的。可以直接换成“=”,査询结果是一样的。

但是,这只对匹配一个完整的字符串这种情况有效。如果字符串中包含了通配符,就不能这样进行替换了。

【示例10-13】下面使用LIKE关键字来匹配带有通配符‘%’的字符串‘北京%’。SELECT语句的代码如下:

SELECT * FROM employee WHERE homeaddr LIKE ’北京%';

代码执行如下:

mysql> SELECT * FROM employee WHERE homeaddr LIKE '北京%';
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
+-----+------+------+-----+-----+--------------+
2 rows in set (0.00 sec)

结果显示,査询出homeaddr字段以“北京”开头的记录。如果使用“=”来代替LIKE, 该SELECT语句的执行结果如下:

SELECT * FROM employee WHERE homeaddr='北京%';
Empty set (0.00 sec)

结果显示,没有查询出任何记录。这说明字符串中包含了通配符时,“=”就不能代替LIKE。

【示例10-14】下面使用LIKE关键字来匹配带有通配符‘_’的字符串‘Ar_c’。SELECT语句的代码如下:

SELECT * FROM employee WHERE name LIKE 'r_c';

代码执行如下:

mysql> SELECT * FROM employee WHERE name LIKE "Ar_c";
+-----+------+------+-----+-----+----------+
| num | d_id | name | age | sex | homeaddr |
+-----+------+------+-----+-----+----------+
|   4 | 1004 | Aric |  15 | 男    | England  |
+-----+------+------+-----+-----+----------+
1 row in set (0.00 sec)

结果显示,查询出name字段的取值是AriC的记录。“_”只能代表一个字符。如果字符串为“Ar_”,将不能查询出结果。匹配“Ar_”字符串的代码执行如下:

SELECT * FROM employee WHERE name LIKE "Ar_";
Empty set (0.00 sec)

结果显示,没有查询出任何记录。因为name字段中不存在以“Ar”开头,长度为3 的记录。

注意:需要匹配的字符串需要加引号。可以是单引号,也可以是双引号。如果要匹配姓张且名字只有两个字的人的记录,“张”字后面必须有两个“_”符号。因为一个汉字是两个字符,而一个“_”符号只能代表一个字符。因此,匹配的字符串 应该为“张_ _”,必须是两个“_”符号。

NOT LIKE表示字符串不匹配的情况下满足条件。

【示例10-15】下面使用NOT LIKE关键字来查询不是姓张的所有人的记录。SELECT 语句的代码如下:

SELECT * FROM employee WHERE name NOT LIKE "张%";

代码执行如下:

mysql> SELECT * FROM employee WHERE name NOT LIKE "张%";
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
3 rows in set (0.00 sec)

结果显示,name字段的值为“张三”的记录被排除出去。使用LIKE和NOT LIKE关键字可以很好的匹配字符串。而且,可以使用“%”和“_”这两个通配字符来简化查询。

10.2.7 空值查询

IS NULL关键字可以用来判断字段的值是否为空值(NULL)。如果字段的值是空值, 则满足查询条件,该记录将被查询出来。如果字段的值不是空值,则不满足查询条件。其语法规则如下:

IS [NOT] NULL

其中,“NOT”是可选参数,加上NOT表示字段不是空值时满足条件。

【示例10-16】下面使用IS NULL关键字来查询work表中info字段为空值的记录。 SELECT语句的代码如下:

SELECT * FROM work WHERE info IS NULL;

代码执行如下:

mysql> select * from work where info is null;
+------+------+------+------+
| id   | name | sex  | info |
+------+------+------+------+
| 1001 | hjh  |      | NULL |
| 1002 | cch  | NULL | NULL |
+------+------+------+------+
2 rows in set (0.00 sec)

mysql>

结果显示,info字段为空值的记录都被査询出来。

注意:IS NULL是一个整体,不能将替换成“=”。如果将IS换成“=”将不能查询出任何结果,数据库系统会出现“Emptyset(O.OOsec)”这样的提示。同理,IS NOT NULL中的IS不能换成“!=”或<>”。

如果使用IS NOT NULL关键字,将查询出该段的值不为空的所有记录。

【示例10-17】下面使用IS NOT NULL关键字来查询work表中info字段不为空值的记录。SELECT语句的代码如下:

SELECT * FROM work WHERE info IS NOT NULL ;

结果显示,查询出来的记录中info字段不为空值。

10.2.8带AND的多条件查询

AND关键字可以用来联合多个条件进行查询。使用AND关键字时,只有同时满足所有査询条件的记录会被查询出来。如果不满足这些查询条件的其中一个,这样的记录将被排除掉。AND关键字的语法规则如下:

条件表达式1 AND 条件表达式2 [...AND条件表达式n]

其中,AND可以连接两个条件表达式。而且,可以同时使用多个AND关键字,这样可以连接更多的条件表达式。

【示例10-18】下面使用AND关键字来查询employee表中d_id为1001,而且sex为 ‘男’的记录。SELECT语句的代码如下:

SELECT * FROM employee WHERE d_id=1001 AND sex LIKE '男';

代码执行如下:

mysql> SELECT * FROM employee WHERE d_id=1001 AND sex LIKE '男';
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
+-----+------+------+-----+-----+--------------+
1 row in set (0.00 sec)

结果显示,满足d_id为1001,而且sex为“男”的记录被查询出来。因为要同时满足AND的所有条件,所以查询出来的记录会相对较少。

【示例10-19】下面在employee表中查询d_id小于1004,age小于26,而且sex为“男” 的记录。SELECT语句的代码如下:

SELECT * FROM employee WHERE d_id<1004 AND age<26 AND sex='男';

代码执行如下:

mysql> SELECT * FROM employee WHERE d_id<1004 AND age<26 AND sex='男';
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
+-----+------+------+-----+-----+--------------+
1 row in set (0.00 sec)

查询出来的结果正好满足这3个条件。本例中使用了 “<”和“=”这两个运算符。其"="可以用LIKE替换。

【示例10-20】下面使用AND关键字查询employee表中的记录。查询条件为num取 值在{1,2,3}这个集合中,age范围从15~25,而且,homeaddr的取值中包含‘北京市’。

SELECT * FROM employee WHERE num IN (1,2,3) AND age BETWEEN 15 AND 25 AND homeaddr LIKE '%北京市%';

代码执行如下:

mysql> SELECT * FROM employee WHERE num IN (1,2,3) AND age BETWEEN 15 AND 25 AND homeaddr LIKE '%北京市%';
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
+-----+------+------+-----+-----+--------------+
1 row in set (0.00 sec)

10.2.9带OR的多条件查询

OR关键字也可以用来联合多个条件进行査询,但是与AND关键字不同。使用OR关键字时,只要满足这几个査询条件的其中一个,这样的记录将会被查询出来。如果不满足这些查询条件中的任何一个,这样的记录将被排除掉。OR关键字的语法规则如下:

条件表达式1 OR 条件表达式2 [...OR条件表达式n]

其中,OR可以用来连接两个条件表达式。而且,可以同时使用多个OR关键字,这样可以连接更多的条件表达式。

【示例10-21】下面使用OR关键字来査询employee表中d_id为1001,或者sex为‘男,的记录。SELECT语句的代码如下:

SELECT * FROM employee WHERE d_id=1001 OR sex LIKE '男';

代码执行如下:

mysql> SELECT * FROM employee WHERE d_id=1001 OR sex LIKE '男';
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
3 rows in set (0.01 sec)

结果显示,num的值为3和4的记录d_id不等于1001。但是,这两条记录的sex字段为“男”。这两条记录也被查询出来。这说明,使用OR关键字时,只要满足多个条件中的其中一个,就可以被查询出来。

【示例10-22】下面使用OR关键字查询employee表中的记录。查询条件为num取值在{1,2,3}这个集合中,或者age从24~25这个范围,或者homeaddr的取值中包含'北京市'。

SELECT * FROM employee WHERE num IN (1,2,3) OR age BETWEEN 24 AND 25 OR homeaddr LIKE '%北京市%';

代码执行如下:

+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
+-----+------+------+-----+-----+--------------+
3 rows in set (0.00 sec)

本例中也使用了前面学过的IN、BETWEEN AND和LIKE关键字。同样使用了通配符“%”。只要满足这三个条件表达式中的任何一个,这样的记录将被查询出来。OR可以和AND—起使用。当两者一起使用时,AND要比OR先运算。

10.2.10 查询结果不重复

如果表中的某些字段上没有唯一性约束,这些字段可能存在着重复的值。例如,employee表中的d_id字段就存在着重复的情况。

employee表中有两条记录的d_id的值为1001。SELECT语句中可以使用DISTINCT关键字来消除重复的记录。其语法规则如下:

SELECT DISTINCT 属性名

其中,“属性名”参数表示要消除重复记录的字段的名词。

【示例10-24】下面使用DISTINCT关键字来消除d_id字段中的重复记录。带DISTINCT关键字的SELECT语句如下:

SELECT DISTINCT d_id FROM employee;

在执行该SELECT语句之前,先查看d_id字段的实际情况。代码执行如下:

mysql> SELECT DISTINCT d_id FROM employee;
+------+
| d_id |
+------+
| 1001 |
| 1001 |
| 1002 |
| 1004 |
+------+
4 rows in set (0.01 sec)

结果显示,employee表中存在两条值为1001的记录。下面执行带DISTINCT关键字的SELECT语句。比较使用DISTINCT关键字前后的差异。代码执行如下:

mysql> SELECT DISTINCT d_id FROM employee;
+------+
| d_id |
+------+
| 1001 |
| 1002 |
| 1004 |
+------+
3 rows in set (0.01 sec)

结果显示,D_ID字段只有一条值为1001的记录。这说明,使用DISTINCT关键字消除了重复的记录。

技巧:DISTINCT关键字非常有用,尤其是重复的记录非常多时。例如,需要从消息表中查询有哪些消息。但是,这个表中可能有很多相同的消息,将这些相同的消息都查询出来显然是没有必要的。那么,这就需要DlSTlNCT关键字消除相同的记录。

10.2.11 对查询结果排序

从表中查询出来的数据可能是无序的,或者其排列顺序不是用户所期望的顺序。为了使查询结果的顺序满足用户的要求,可以使用ORDER BY关键字对记录进行排序。其语法规则如下:

ORDER BY 属性名[ASC|DESC]

其中,“属性名”参数表示按照该字段进行排序;ASC参数表示按升序的顺序进行排序;DESC参数表示按降序的顺序进行排序。默认的情况卜,按照ASC方式进行排序。

【示例10-25】下面査询employee表中所有记录,按照ASC字段进行排序。带ORDER BY关键字的SELECT语句如下:

SELECT * FROM employee ORDER BY age;

在执行该SELECT语句之前,先查看employee表中的原始的排序情况。代码执行如下:

mysql> select * from employee;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
4 rows in set (0.00 sec)

结果显示,employee表中的记录是按照age字段的值进行排序的。而且,是按照age字段的升序方式进行排序。本例说明,ORDER BY关键字可以设置查询结果按某个字段进行排序。而且,默认情况下是按升序排列的。

【示例10-26】下面查询employee表中所有记录,按照age字段的升序方式进行排序。 SELECT语句如下:

SELECT * FROM employee ORDER BY age ASC;

代码执行如下:

mysql> SELECT * FROM employee ORDER BY age ASC;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   4 | 1004 | Aric |  15 | 男    | England      |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
+-----+------+------+-----+-----+--------------+
4 rows in set (0.00 sec)

结果显示,记录按照ASC字段的升序的方式进行排序。本例说明,加上ASC参数,记录是按照升序的方式排列的。

【示例10-27】下面査询employee表中所有记录,按照age字段的降序方式进行排序。SELECT语句如下:

SELECT * FROM employee ORDER BY age DESC;

代码执行如下:

mysql> SELECT * FROM employee ORDER BY age DESC;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
4 rows in set (0.00 sec)

结果显示,记录按照age字段的降序的方式进行排序。本例说明,加上DESC参数, 记录是按照升序的方式排列的。

注意:在【示例10-26】中,如果存在一条记录age字段的值为空值(NULL)时,这条记录将显示为第一条记录。因为,按升序排序时,含空值的记录将最先显示。可以理解为空值是该字段的最小值。而按降序排列时,age字段为空值的记录将最后显示。

MySQL中,可以指定按多个字段进行排序。例如,可以使employee表按照d_id字段和age字段进行排序。排序过程中,先按照d_id字段进行排序。遇到d_id字段的值相等的情况时,再把d_id值相等的记录按照age字段进行排序。

【示例10-28】下面査询employee表中所有记录,按照d_id字段的升序方式和age字段的降序方式进行排序。SELECT语句如下:

SELECT * FROM employee ORDER BY d_id ASC,age DESC;

代码执行如下:

mysql> SELECT * FROM employee ORDER BY d_id ASC,age DESC;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
4 rows in set (0.00 sec)

查询结果排序时,先按照d_id字段的升序进行排序。因为有两条d_id=1001的记录, 这两条记录按照age字段的降序进行排列。

10.2.12分组查询

GROUP BY关键字可以将查询结果按某个字段或多个字段进行分组。字段中值相等的为一组。其语法规则如下:

GROUP BY 属性名[HAVING 条件表达式][WITH ROLLUP]

其中,“属性名”是指按照该字段的值进行分组;“HAVING条件表达式”用来限制分组后的显示,满足条件表达式的结果将被显示;WITH ROLLUP关键字将会在所有记录的最后加上一条记录。该记录是上面所有记录的总和。

GROUP BY关键字可以和GROUP_CONCAT()函数一起使用。GROUP_CONCAT() 数会把每个分组中指定字段值都显示出来。同时,GROUP BY关键字通常与集合函数一起使用。集合函数包括COUNT()、SUM(), AVG()> MAX和MIN()。 其中,COUNT()用来统计记录的条数;SUN()用来计算字段的值的总和;AVG()用来计算字段的值的平均值; MAX()用来查询字段的最大值;MIN()用来查询字段的最小值。关于集合函数的详细内容 见10.3节。如果GROUP BY不与上述函数一起使用,那么査询结果就是字段取值的分组情况。字段中取值相同的记录为一组,但只显示该组的第一条记录。

1.单独使用GROUP BY关键字来分组

如果单独使用GROUP BY关键字,查询结果只显示一个分组的一条记录。

【示例10-29】下面按employee表的sex字段进行分组查询,查询结果与分组前结果进行对比。先执行不带GROUP BY关键字的SELECT语句。语句执行如下:

mysql> SELECT * FROM employee ORDER BY age DESC;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
4 rows in set (0.00 sec)

带有GROUP BY关键字的SELECT语句的代码如下:

SELECT * FROM employee GROUP BY sex;

代码执行如下:

mysql> SELECT * FROM employee GROUP BY sex;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
+-----+------+------+-----+-----+--------------+
2 rows in set (0.00 sec)

结果中只显示了两条记录。这两条记录的3以字段的值分别为“女”和“男”。查询结果进行比较,GROUP BY关键字只显示每个分组的一条记录。这说明,GROUP BY键字单独使用时,只能査询出每个分组的一条记录。这样使用的意义不大。因此,一般在使用集合函数时才使用GROUP BY关键字。

GROUP BY关键字与GROUP_CONCAT()函数一起使用

GROUP BY关键字与GROUP_CONCAT()函数一起使用时,每个分组中指定字段值都显示出来。【示例10-30】下面按employee表的sex字段进行分组査询。使用GROUP_CONCAT()函数将每个分组的name字段的值显示出来。SELECT语句的代码如下:

SELECT sex, GROUP_CONCAT(name) FROM employee GROUP BY sex;

代码执行如下:

mysql> SELECT sex, GROUP_CONCAT(name) FROM employee GROUP BY sex;
+-----+--------------------+
| sex | GROUP_CONCAT(name) |
+-----+--------------------+
| 女   | 李四                   |
| 男    | 张三,王五,Aric             |
+-----+--------------------+
2 rows in set (0.00 sec)

结果显示,查询结果分为两组。sex字段取值为“女”的记录是一组,取值为“男”的记录为一组。而且,每一组中所有人的名字都被查询出来。该例说明,使用 GROUP_CONCAT()函数可以很好的把分组情况表示出来。

3.GROUP BY关键字与集合函数一起使用

GROUP BY关键字与集合函数一起使用时,可以通过集合函数计算分组中的总记录、 最大值、最小值等。

【示例10-31】下面按employee表的sex字段进行分组查询。sex字段取值相同的为一组。然后对每一组使用集合函数COUNT()进行计算,求出每一组的记录数。SELECT语句的代码如下:

SELECT sex, COUNT(sex) FROM employee GROUP BY sex;

代码执行如下:

mysql> SELECT sex, COUNT(sex) FROM employee GROUP BY sex;
+-----+------------+
| sex | COUNT(sex) |
+-----+------------+
| 女   |          1 |
| 男    |          3 |
+-----+------------+
2 rows in set (0.01 sec)

结果显示,查询结果按sex字段取值进行分组。取值为“女”的记录是一组,.取值为 “男”的记录是一组。COUNT(Sex)计算出了sex字段不同分组的记录数。第一组只有1条记录,第二组共有3条记录。

技巧:通常情况下,GROUP BY关键字与集合函数一起使用。集合函数包括COUNT(),SUM(), AVG(), MAX((),Mm().通常先使用GROUP BY关键字将记录分组, 然后每组都使用集合函数进行计算。在统计时经常需要使用GROUP BY关键字和集合函数。

4.GROUP BY关键与HAVING—起使用

如果加上“HAVING 条件表达式”,可以限制输出的结果。只有满足条件表达式的结果才会显示。

【示例10-32】下面按employee表的sex字段进行分组查询。然后显示记录数大于等于3的分组。SELECT语句的代码如下:

SELECT sex, COUNT(sex) FROM employee GROUP BY sex HAVING COUNT(sex)>=3;

查询结果只显示了取值为“男”的记录的情况。因为,该分组的记录数为3,刚好满足HAVING COUNT(sex)>=3的条件。从本例可以看出,“HAVING条件表达式”可以限制查询结果的显示情况。

说明:“HAVING条件表达式”与“WHERE条件表达式”都是用来限制显示的。但是,两者起作用的地方不一样。“WHERE条件表达式”作用于表或者视图,是 表和视图的查询条件。“HAVING条件表达式”作用于分组后的记录,用于选择满足条件的组。

5.按多个字段进行分组

MySQL中,还可以按多个字段进行分组。例如,employee表按照d_id字段和sex字段进行分组。分组过程中,先按照d_id字段进行分组。遇到d_id字段的值相等的情况时, 再把d_id值相等的记录按照sex字段进行分组。

【示例10-33】下面employee表按照d_id字段和sex字段进行分组。SELECT语句如下:

SELECT * FROM employee GROUP BY d_id, sex ;
mysql> SELECT * FROM employee GROUP BY d_id, sex ;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
|   4 | 1004 | Aric |  15 | 男    | England      |
+-----+------+------+-----+-----+--------------+
4 rows in set (0.00 sec)

查询结果显示,记录先按照d_id字段进行分组。因为有两条记录的d_id值为1001,所以这两条记录按照age字段的取值进行分组。

6.GROUP BY关键与WITH ROLLUP一起使用


使用WITH ROLLUP时,将会在所有记录的最后加上一条记录。这条记录是上面所有记录的总和。

【示例10-34】下面按employee表的sex字段进行分组查询。使用COUNT()函数来计算每组的记录数。并且加上界WITH ROLLUP。SELECT语句如下:

SELECT sex, COUNT(sex) FROM employee GROUP BY sex WITH ROLLUP;


代码执行如下:

mysql> SELECT sex, COUNT(sex) FROM employee GROUP BY sex WITH ROLLUP;
+-----+------------+
| sex | COUNT(sex) |
+-----+------------+
| 女   |          1 |
| 男    |          3 |
| NULL |          4 |
+-----+------------+
3 rows in set (0.01 sec)

查询结果显示,计算出了各个分组的记录数。并且,在记录的最后加上了一条新的记录。该记录的COUNT()列的值刚好是上面分组的值的总和。

10.2.13用LIMIT限制查询结果的数量

查询数据时,可能会查询出很多的记录。而用户需要的记录可能只是很少的一部分。 这样就需要来限制查询结果的数量。LIMIT是MySQL中的一个特殊关键字。其可以用来 指定查询结果从哪条记录开始显示。还可以指定一共显示多少条记录。LIMIT关键字有两种使用方式。这两种方式分别是不指定初始位置和指定初始位置。

1.不指定初始位置

LIMIT关键字不指定初始位置时,记录从第一条记录开始显示。显示记录的条数有limit关键字指定。其语法规则如下:

LIMIT 记录数

其中,“记录数”参数表示显示记录的条数。如果“记录数”的值小于查询结果的总 记录数,将会从第一条记录开始,显示指定条数的记录。如果“记录数”的值大于查询结 果的总记录数,数据库系统会直接显示查询出来的所有记录。

【示例10-36】下面查询employee表的所有记录。但只显示前两条。SELECT语句 如下:

SELECT * FROM employee LIMIT 2 ;

执行结果如下:

mysql> SELECT * FROM employee LIMIT 2 ;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
+-----+------+------+-----+-----+--------------+
2 rows in set (0.00 sec)

结果中只显示了两条记录。该例说明“LIMIT2”限制了显示条数为2。

【示例10-37】下面查询employee表的所有记录;但只显示前6条。SELECT语句如下:

SELECT * FROM employee LIMIT 6 ;

执行结果如下:

mysql> SELECT * FROM employee LIMIT6;
4 rows in set (0.00 sec)

结果中只显示了4条记录。虽然LIMIT关键字指定了显示6条记录。但是查询结果中 只有4条记录。因此,数据库系统就将这4条记录全部显示出来。

2.指定初始位置

LIMIT关键字可以指定从哪条记录开始显示,并且可以指定显示多少条记录。其语法规则如下:

LIMIT初始位置,记录数

其中,“初始位置”参数指定从哪条记录开始显示;“记录数”参数表示显示记录的 条数。第一条记录的位置是0,第二条记录的位置是1。后面的记录依次类推。

【示例10-38】下面查询employee表的所有记录,显示前两条记录。SELECT语句如下:

SELECT * FROM employee LIMIT 0, 2 ;

执行结果如下:

mysql> SELECT * FROM employee LIMIT 0, 2 ;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   1 | 1001 | 张三     |  26 | 男    | 北京市海淀区            |
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
+-----+------+------+-----+-----+--------------+
2 rows in set (0.00 sec)

结果中只显示了前两条记录。从结果可以看出,“LIMIT 0,2”和“LIMIT 2”是一个意思,都是显示前两条记录。

【示例10-39】下面查询employee表的所有记录。从第二条记录开始显示,共显示两条记录。SELECT语句如下:

SELECT * FROM employee LIMIT 1, 2 ;

执行结果如下:

mysql> SELECT * FROM employee LIMIT 1, 2 ;
+-----+------+------+-----+-----+--------------+
| num | d_id | name | age | sex | homeaddr     |
+-----+------+------+-----+-----+--------------+
|   2 | 1002 | 李四     |  24 | 女   | 北京市昌平区           |
|   3 | 1003 | 王五     |  25 | 男    | 湖南省长沙市           |
+-----+------+------+-----+-----+--------------+
2 rows in set (0.00 sec)

结果中只显示了第2和第3条记录。这个例子可以看出,LIMIT关键字可以指定从哪条记录开始显示,也可以指定显示多少条记录。

技巧:LIMIT关键字是MYSQL中所特有的。LIMIT关键字可以指定需要显示的记录的初始位置,0表示第一条记录。如果需要查询成绩在前十名的学生的信息,可以使用ORDER BY关键字将记录按照分数的降序排列,然后使用LIMIT关键字指定只查询前10条记录。


关注微信获取最新动态