您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

mysql SELECT查询_MySQL

2024/3/31 16:45:16发布12次查看
一、单表查询
1、一般查询。2、聚合函数、排序 3、别名。4、分组。5、分组过滤。6、限制显示条目。7、杂项。
二、多表查询
1、联结查询。2、子查询。3、联合查询。
数据库版本:5.5.46-mariadb
说明一下这几张表,这是在上马哥课程的时候给的生成表的sql备份文件。
在文章最后我把它放到附件中。
注意:在linux上表名是区分大小写的。
如果搞不清语句顺序请看:help select
一、单表查询
1、一般查询
mariadb [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| stuid | name          | age | gender | classid | teacherid |
+-------+---------------+-----+--------+---------+-----------+
|     1 | shi zhongyu   |  22 | m      |       2 |         3 |
|     2 | shi potian    |  22 | m      |       1 |         7 |
|     3 | xie yanke     |  53 | m      |       2 |        16 |
|     4 | ding dian     |  32 | m      |       4 |         4 |
|     5 | yu yutong     |  26 | m      |       3 |         1 |
|     6 | shi qing      |  46 | m      |       5 |      null |
|     7 | xi ren        |  19 | f      |       3 |      null |
|     8 | lin daiyu     |  17 | f      |       7 |      null |
|     9 | ren yingying  |  20 | f      |       6 |      null |
|    10 | yue lingshan  |  19 | f      |       3 |      null |
|    11 | yuan chengzhi |  23 | m      |       6 |      null |
|    12 | wen qingqing  |  19 | f      |       1 |      null |
|    13 | tian boguang  |  33 | m      |       2 |      null |
|    14 | lu wushuang   |  17 | f      |       3 |      null |
|    15 | duan yu       |  19 | m      |       4 |      null |
|    16 | xu zhu        |  21 | m      |       1 |      null |
|    17 | lin chong     |  25 | m      |       4 |      null |
|    18 | hua rong      |  23 | m      |       7 |      null |
|    19 | xue baochai   |  18 | f      |       6 |      null |
|    20 | diao chan     |  19 | f      |       7 |      null |
|    21 | huang yueying |  22 | f      |       6 |      null |
|    22 | xiao qiao     |  20 | f      |       1 |      null |
|    23 | ma chao       |  23 | m      |       4 |      null |
|    24 | xu xian       |  27 | m      |    null |      null |
|    25 | sun dasheng   | 100 | m      |    null |      null |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.05 sec)
mariadb [hellodb]> select stuid,name,age from students where age > 25;
+-------+--------------+-----+
| stuid | name         | age |
+-------+--------------+-----+
|     3 | xie yanke    |  53 |
|     4 | ding dian    |  32 |
|     5 | yu yutong    |  26 |
|     6 | shi qing     |  46 |
|    13 | tian boguang |  33 |
|    24 | xu xian      |  27 |
|    25 | sun dasheng  | 100 |
+-------+--------------+-----+
7 rows in set (0.02 sec)
select中的where子句就是一个布尔条件表达式,来判断行是否区配表达式。只要返回的为真,也就是不为0,则where子句就为真,就会显示匹配的行。
布尔条件表达式操作符:
= 等于,用于数值或字符都可以。
也是等值比较,不过不会跟空产生意外情况。是跟空值比较的安全方式。
不等于,这个就只能用于数值了。
>
>=
空字符跟空是不一样的。 空字符也是一种字符串,也是有自己的ascii码和值的。           
is null 判断是否为空
is not null 判断是否为不空
like
模糊匹配,支持通配符,% 百分号表示任意个任意字符。_ 下划线任意单个字符。在能用等值比较或不等值比较的情况下不要用like,性能差的多。
rlike,regexp
支持使用正则表达式。性能更低。like, rlike只能用来做字符的比较。
也可以完整的匹配数值,不过也没有意义。
in 
判断指定的字段的值是否在给定的列表中, in (‘abc','cc')
between  and
判断指定的字段是否在给定的范围之间。
如 x>=20 and x
组合条件:  
not ,!
and ,,&&
or,||
注意: 在mysql中只要是字符型的在使用的时候都要加引号,而如果是数值型的,一定不能加引号。
例1:is null, 判断classid字段为空的记录。只显示name,age,classid.
mariadb [hellodb]> select name,age,classid from students where classid is null;
+-------------+-----+---------+
| name        | age | classid |
+-------------+-----+---------+
| xu xian     |  27 |    null |
| sun dasheng | 100 |    null |
+-------------+-----+---------+
2 rows in set (0.00 sec)
例2:用like来模糊匹配name字段所有以x开头的行。%通配任意个任意字符。
mariadb [hellodb]> select name from students where name like 'x%';
+-------------+
| name        |
+-------------+
| xie yanke   |
| xi ren      |
| xu zhu      |
| xue baochai |
| xiao qiao   |
| xu xian     |
+-------------+
6 rows in set (0.00 sec)
下面的效果跟上面的相同。这里是用正则表达式匹配的。
1
mariadb [hellodb]> select name from students where name rlike '^x.*';
例3:in。下面是查找classid是1或3或5的记录。只显示name和classid字段。
mariadb [hellodb]> select name,classid from students where classid in (1,3,5);
+--------------+---------+
| name         | classid |
+--------------+---------+
| shi potian   |       1 |
| yu yutong    |       3 |
| shi qing     |       5 |
| xi ren       |       3 |
| yue lingshan |       3 |
| wen qingqing |       1 |
| lu wushuang  |       3 |
| xu zhu       |       1 |
| xiao qiao    |       1 |
+--------------+---------+
9 rows in set (0.00 sec)
mariadb [hellodb]>
例4:between  and ,匹配一个范围。年龄在30到50之间。
mariadb [hellodb]> select name,age from students where age between 30 and 50;
+--------------+-----+
| name         | age |
+--------------+-----+
| ding dian    |  32 |
| shi qing     |  46 |
| tian boguang |  33 |
+--------------+-----+
3 rows in set (0.00 sec)
mariadb [hellodb]>
例5:组合and,gender为m,并且,age大于30或等于20。这个括号是一定要有的,不然就变成“gender为m并且age大于30,或者age等于20。
mariadb [hellodb]> select * from students where gender='m' and (age > 30 or age = 20);
+-------+--------------+-----+--------+---------+-----------+
| stuid | name         | age | gender | classid | teacherid |
+-------+--------------+-----+--------+---------+-----------+
|     3 | xie yanke    |  53 | m      |       2 |        16 |
|     4 | ding dian    |  32 | m      |       4 |         4 |
|     6 | shi qing     |  46 | m      |       5 |      null |
|    13 | tian boguang |  33 | m      |       2 |      null |
|    25 | sun dasheng  | 100 | m      |    null |      null |
+-------+--------------+-----+--------+---------+-----------+
5 rows in set (0.01 sec)
想以年龄排序。可以用
order by  [asc|desc|字段]
asc表示升序, desc表示降序。  默认是asc
以年龄降序排列。
mariadb [hellodb]> select * from students where gender='m' and (age > 30 or age = 20) order by age desc;
+-------+--------------+-----+--------+---------+-----------+
| stuid | name         | age | gender | classid | teacherid |
+-------+--------------+-----+--------+---------+-----------+
|    25 | sun dasheng  | 100 | m      |    null |      null |
|     3 | xie yanke    |  53 | m      |       2 |        16 |
|     6 | shi qing     |  46 | m      |       5 |      null |
|    13 | tian boguang |  33 | m      |       2 |      null |
|     4 | ding dian    |  32 | m      |       4 |         4 |
+-------+--------------+-----+--------+---------+-----------+
5 rows in set (0.01 sec)
mariadb [hellodb]>
这些只是一般的查询,如果要统计数据,就要用聚合函数了。
2、聚合函数。
话说想统计下一共有多少人,或者女的有多少,男的有多少,平均年龄,最小最大年龄。
sum(), avg(), max(), min(), count()
分别是求和、平均值、最大、最小、统计个数。这几个是常用到的。
例6:sum(),全体同学年龄总和。可以用where加上条件,如男同学的年龄总和。
mariadb [hellodb]> select sum(age) from students;
+----------+
| sum(age) |
+----------+
|      685 |
+----------+
1 row in set (0.00 sec)
也可以显示其它字段,不过也只是一行。
例7:avg(),全体同学的年龄平均值。
mariadb [hellodb]> select avg(age) from students;
+----------+
| avg(age) |
+----------+
|  27.4000 |
+----------+
1 row in set (0.00 sec)
例8:count(), 统计一共多少学生。count后面有的会使用*。count(*),这样也可以,不过性能差点。
mariadb [hellodb]> select count(name) from students;
+-------------+
| count(name) |
+-------------+
|          25 |
+-------------+
1 row in set (0.00 sec)
我们也可以不让它显示上面的字段名称,给它换一个名称。
3、as  别名。
mariadb [hellodb]> select count(name) as cc from students;
+----+
| cc |
+----+
| 25 |
+----+
1 row in set (0.00 sec)
还有表也可以有别名,在多表查询的时候再来说说。
下面男同学的最小年龄,并用别名显示。
mariadb [hellodb]> select min(age) as min_m from students where gender = 'm';
+-------+
| min_m |
+-------+
|    19 |
+-------+
1 row in set (0.00 sec)
可不可以一次性男女分开显示各自的最小年龄。那就要用分组了。可以按性别gender来分组。这样函数就会分别计算各组的数据。
4、分组。
group by 字段名
以字段的值分组。同一个值一个组。然后再通过用聚合函数来统计不同组中的信息。
现在以gender分组,也就是两组。函数分别计算两个组。
不过下面这个有点缺陷,不知道哪是女的,哪个是男的。
mariadb [hellodb]> select min(age) from students group by gender;
+----------+
| min(age) |
+----------+
|       17 |
|       19 |
+----------+
2 rows in set (0.00 sec)
mariadb [hellodb]>
下面再显示出来性别字段。
mariadb [hellodb]> select min(age),gender from students group by gender;
+----------+--------+
| min(age) | gender |
+----------+--------+
|       17 | f      |
|       19 | m      |
+----------+--------+
2 rows in set (0.00 sec)
mariadb [hellodb]>
例:显示不同班级的学生个数
mariadb [hellodb]> select count(name),classid from students group by classid;
+-------------+---------+
| count(name) | classid |
+-------------+---------+
|           2 |    null |
|           4 |       1 |
|           3 |       2 |
|           4 |       3 |
|           4 |       4 |
|           1 |       5 |
|           4 |       6 |
|           3 |       7 |
+-------------+---------+
8 rows in set (0.00 sec)
mariadb [hellodb]>
不显示没有班级的。where在分组之前先进行过滤,然后把数据再给group by来进行分组。
mariadb [hellodb]> select count(name),classid from students where classid is not null group by classid;
+-------------+---------+
| count(name) | classid |
+-------------+---------+
|           4 |       1 |
|           3 |       2 |
|           4 |       3 |
|           4 |       4 |
|           1 |       5 |
|           4 |       6 |
|           3 |       7 |
+-------------+---------+
7 rows in set (0.00 sec)
mariadb [hellodb]>
例9:各个班级的平均年龄。
mariadb [hellodb]> select avg(age),classid from students group by classid;
+----------+---------+
| avg(age) | classid |
+----------+---------+
|  63.5000 |    null |
|  20.5000 |       1 |
|  36.0000 |       2 |
|  20.2500 |       3 |
|  24.7500 |       4 |
|  46.0000 |       5 |
|  20.7500 |       6 |
|  19.6667 |       7 |
+----------+---------+
8 rows in set (0.00 sec)
mariadb [hellodb]>
加上排序呢:
mariadb [hellodb]> select avg(age),classid from students group by classid order by avg(age);
+----------+---------+
| avg(age) | classid |
+----------+---------+
|  19.6667 |       7 |
|  20.2500 |       3 |
|  20.5000 |       1 |
|  20.7500 |       6 |
|  24.7500 |       4 |
|  36.0000 |       2 |
|  46.0000 |       5 |
|  63.5000 |    null |
+----------+---------+
8 rows in set (0.00 sec)
意思就是在分组之后,把各个分组重新排序了。以各个组的age字段的平均值来排序。
回来看分组:如果不想显示平均年龄小于等于25的,怎么办呢。
5、分组过滤。
having 用于对分组做条件过滤。
普及:where是对表中的每一行做过滤,单位是行。 而having是对每一个组做过滤,单位是组。
如:
mariadb [hellodb]> select avg(age),classid from students group by classid having avg(age)>25;
+----------+---------+
| avg(age) | classid |
+----------+---------+
|  63.5000 |    null |
|  36.0000 |       2 |
|  46.0000 |       5 |
+----------+---------+
3 rows in set (0.00 sec)
mariadb [hellodb]>
having拿到手的都是一组一组的数据,所以也要求下平均值。然后不匹配的组,就刷掉。到了select那里,它求一下平均值是为了显示。这是两个不同的部分。
如果想找age小于avg(age)之类的结果,这里是查不出来的。在子查询部分。
例10:显示最少有3个同学的班级和该班级的人数。
mariadb [hellodb]> select classid,count(name) from students group by classid having count(name) >= 3;
+---------+-------------+
| classid | count(name) |
+---------+-------------+
|       1 |           4 |
|       2 |           3 |
|       3 |           4 |
|       4 |           4 |
|       6 |           4 |
|       7 |           3 |
+---------+-------------+
6 rows in set (0.00 sec)
mariadb [hellodb]>
这个表小,这样显示还可以,但是如果有上千上万个的条目,一下子显示出来就有点夸张了,占网络带宽不说,一下子出来这么多,也看不完啊。
6、限制显示条目的数量。
limit
只显示3行。在最后加上limit 3就可以了。
mariadb [hellodb]> select * from students limit 3;
+-------+-------------+-----+--------+---------+-----------+
| stuid | name        | age | gender | classid | teacherid |
+-------+-------------+-----+--------+---------+-----------+
|     1 | shi zhongyu |  22 | m      |       2 |         3 |
|     2 | shi potian  |  22 | m      |       1 |         7 |
|     3 | xie yanke   |  53 | m      |       2 |        16 |
+-------+-------------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)
这是从头开始,显示3行。如果想从中间开始。下面这个是从第5行开始,显示3行。
mariadb [hellodb]> select * from students limit 5,3;
+-------+-----------+-----+--------+---------+-----------+
| stuid | name      | age | gender | classid | teacherid |
+-------+-----------+-----+--------+---------+-----------+
|     6 | shi qing  |  46 | m      |       5 |      null |
|     7 | xi ren    |  19 | f      |       3 |      null |
|     8 | lin daiyu |  17 | f      |       7 |      null |
+-------+-----------+-----+--------+---------+-----------+
3 rows in set (0.00 sec)
7、杂项。
distinct  :  指定的结果相同的只显示一次。在select 语句后面。
sql_cache :  缓存此条语句至查询缓存中。
sql_no_cache:  说明不缓存此条语句。
简单的例子说明下第一个吧。如果显示都有哪些年龄的同学,除了用分组外。还可以用distinct。只不过只能显示一个字段。
age字段重复的就不显示,并且排序。 不排序也没有关系。
mariadb [hellodb]> select distinct age  from students order by age;
+-----+
| age |
+-----+
|  17 |
|  18 |
|  19 |
|  20 |
|  21 |
|  22 |
|  23 |
|  25 |
|  26 |
|  27 |
|  32 |
|  33 |
|  46 |
|  53 |
| 100 |
+-----+
15 rows in set (0.00 sec)
到这里单表查询就完了。我们来看看这么多语句它的执行流程。
select语句的执行流程:
from --> where  --> group by --> having  --> order by --> select --> limit
首先是from获取表数据,然后where筛选,再然后group by来分组,再然后having给组再来一下过滤,再然后就是order by给剩下的组或是整张表的行排序,再然后才是select把最终整理好的数据计算或者直接显示出来,当然到达客户端还要经过limit限制。
二、多表查询。
我们知道关系型数据库就是为了降低冗余,所以都是把内容记录到多张表中,我们在查询的时候要把多张表连起来才能查到所有数据。
说明一下,因为表的内容都贴出来的话就太多了,所以这里就只举例子了,具体的表内容,朋友们自己下载看吧。
mariadb [hellodb]> show tables;
+-------------------+
| tables_in_hellodb |
+-------------------+
| classes           |
| coc               |
| courses           |
| scores            |
| students          |
| teachers          |
| toc               |
+-------------------+
7 rows in set (0.00 sec)
1、联结查询
联结查询: 先将几张表join起来, 然后再根据join以后所产生的表,来进行查询。
有:
交叉联结、自然联结、外联结、自联结。
交叉联结:
就是各个表的各字段的值相乘的关系。各种连结,各种交叉。这里也只是提一下。
直接from表就是了。
1
mariadb [hellodb]> select * from students,coc,classes;
自然联结:
又叫内联结或等值联结,两张表要有相同的字段可以建立联结。用where 联结条件。一般情况下都是使用自然联结。
举例子先,上面的students表中有学生信息,而classes表中有班级的名称。现在想显示学生的名子和所对应的班级名称。
那么就需要student和classes建立结结。正好它们都有classid班级编号。所以:
mariadb [hellodb]> select students.name,classes.class from students,classes where students.classid = classes.classid;
+---------------+----------------+
| name          | class          |
+---------------+----------------+
| shi zhongyu   | emei pai       |
| shi potian    | shaolin pai    |
| xie yanke     | emei pai       |
| ding dian     | wudang pai     |
*
*
23 rows in set (0.00 sec)
中间省略了,不然太多。  上面用where来做两个表的等值条件。
把字段全部显示出来看看:
mariadb [hellodb]> select * from students,classes where students.classid = classes.classid;
+-------+---------------+-----+--------+---------+-----------+---------+----------------+----------+
| stuid | name          | age | gender | classid | teacherid | classid | class          | numofstu |
+-------+---------------+-----+--------+---------+-----------+---------+----------------+----------+
|     1 | shi zhongyu   |  22 | m      |       2 |         3 |       2 | emei pai       |        7 |
|     2 | shi potian    |  22 | m      |       1 |         7 |       1 | shaolin pai    |       10 |
|     3 | xie yanke     |  53 | m      |       2 |        16 |       2 | emei pai       |        7 |
|     4 | ding dian     |  32 | m      |       4 |         4 |       4 | wudang pai     |       12 |
|     5 | yu yutong     |  26 | m      |       3 |         1 |       3 | qingcheng pai  |       11 |
|     6 | shi qing      |  46 | m      |       5 |      null |       5 | riyue shenjiao |       31 |
|     7 | xi ren        |  19 | f      |       3 |      null |       3 | qingcheng pai  |       11 |
classid都是相等的。这里还有一个问题就是,在多表连结的时候会有多个字段一样的,所以在写的时候要把表名也给写上,就是这种格式students.classid之类的。但是有的表名又很长,这个时候就可以用别名了。在from后面的表名后面使用as。from 表名 as 别名
mariadb [hellodb]> select * from students as stu,classes as cla where stu.classid = cla.classid;
+-------+---------------+-----+--------+---------+-----------+---------+----------------+----------+
| stuid | name          | age | gender | classid | teacherid | classid | class          | numofstu |
+-------+---------------+-----+--------+---------+-----------+---------+----------------+----------+
|     1 | shi zhongyu   |  22 | m      |       2 |         3 |       2 | emei pai       |        7 |
|     2 | shi potian    |  22 | m      |       1 |         7 |       1 | shaolin pai    |       10 |
|     3 | xie yanke     |  53 | m      |       2 |        16 |       2 | emei pai       |        7 |
|     4 | ding dian     |  32 | m      |       4 |         4 |       4 | wudang pai     |       12 |
|     5 | yu yutong     |  26 | m      |       3 |         1 |       3 | qingcheng pai  |       11 |
|     6 | shi qing      |  46 | m      |       5 |      null |       5 | riyue shenjiao |       31 |
多表连结也简单,就是表多了以后会晕乎。所以主要问题就是要熟悉自己的各种表。
有内连结,自然就有外连结。内连结把表的字段的数值与另一张表连接起来,但是并不是所有记录都可以连接起来,比如上面的students表中还有两个人没有显示出来,因为他们没有班级。
+-------+---------------+-----+--------+---------+-----------+
| stuid | name          | age | gender | classid | teacherid |
+-------+---------------+-----+--------+---------+-----------+
|    24 | xu xian       |  27 | m      |    null |      null |
|    25 | sun dasheng   | 100 | m      |    null |      null |
+-------+---------------+-----+--------+---------+-----------+
如这两位仁兄。那么如果我也想把这两个显示出来。就要用到外连接了。
外联结:外联结又分为“左外连结和右外连结”。其实意思都一样,就是以哪个为主,主表所有的都显示出来,别一张表如果对不上就为null。
左外联结    以左表为基准,右表没有的为null.
 left_tb left join right_tb on 连接条件
右外联结    以右表为基准,左表没有的为null.
 left_tb right join right_tb on 连接条件
全外联结    以两个表为基准,哪个没有哪个为null.  mysql中没有。
mariadb [hellodb]> select * from students left join classes on students.classid=classes.classid;
+-------+---------------+-----+--------+---------+-----------+---------+----------------+----------+
| stuid | name          | age | gender | classid | teacherid | classid | class          | numofstu |
+-------+---------------+-----+--------+---------+-----------+---------+----------------+----------+
|    18 | hua rong      |  23 | m      |       7 |      null |       7 | ming jiao      |       27 |
|    19 | xue baochai   |  18 | f      |       6 |      null |       6 | lianshan pai   |       27 |
|    20 | diao chan     |  19 | f      |       7 |      null |       7 | ming jiao      |       27 |
|    21 | huang yueying |  22 | f      |       6 |      null |       6 | lianshan pai   |       27 |
|    22 | xiao qiao     |  20 | f      |       1 |      null |       1 | shaolin pai    |       10 |
|    23 | ma chao       |  23 | m      |       4 |      null |       4 | wudang pai     |       12 |
|    24 | xu xian       |  27 | m      |    null |      null |    null | null           |     null |
|    25 | sun dasheng   | 100 | m      |    null |      null |    null | null           |     null |
+-------+---------------+-----+--------+---------+-----------+---------+----------------+----------+
就是这样的了。打个比方,如果classes的表有额外的classid,如8,9,10之类的,而students表中没有,那么也是不会显示出来的。因为左外连接是以左表为准,管你右边的表有什么。而右外连接就是以右边的表为准了。当然在写表的时候把classes表写左边也是一样的。
这些表还可以作三个表甚至四个表连接的操作。比如加上成绩。大家就自己试试吧。
2、子查询:
在查询中嵌套的查询。
用于where中的子查询
1、用于比较表达式中的子查询。子查询的返回值只能有一个
2、用于exists中的子查询,判断存在与否。
3、用于in中的子查询,判断存在于指定的列表中。
4、用于from中的子查询,select * from (select clause) as alias。这里一定要用别名。
5、在select中也可以用子语句的值来作为一个字段。
先解决查询age>avg(age)的问题。为什么在上面那里不能用,因为这种写法就是错的。一行还是一组呢。
1、放到where后,where语句的数据是一行一行的,age是可以表示当前行的age值。但是avg(age)就有问题了,它只能放在group by后面来计算组的平均值,或是select后面全表的平均值。
2、放到having后面,同样的问题。是一组数据。
如果要查询就要用子查询先计算平均值。
查询所有同学年龄大于平均年龄的。
mariadb [hellodb]> select name,age from students where age > (select avg(age) from students);
+--------------+-----+
| name         | age |
+--------------+-----+
| xie yanke    |  53 |
| ding dian    |  32 |
| shi qing     |  46 |
| tian boguang |  33 |
| sun dasheng  | 100 |
+--------------+-----+
5 rows in set (0.00 sec)
延伸一下:显示平均年龄:
mariadb [hellodb]> select name,age,(select avg(age) from students) as avg_age from students where age > (select avg(age) from students);
+--------------+-----+---------+
| name         | age | avg_age |
+--------------+-----+---------+
| xie yanke    |  53 | 27.4000 |
| ding dian    |  32 | 27.4000 |
| shi qing     |  46 | 27.4000 |
| tian boguang |  33 | 27.4000 |
| sun dasheng  | 100 | 27.4000 |
+--------------+-----+---------+
5 rows in set (0.00 sec)
那么再延伸一下,显示在各个班级内同学,大于班级内年龄平均值的。
有点复杂,我这里是这样作的。
第一步:求出各个班内的平均年龄。
mariadb [hellodb]> select avg(age),classid from students group by classid;
+----------+---------+
| avg(age) | classid |
+----------+---------+
|  63.5000 |    null |
|  20.5000 |       1 |
|  36.0000 |       2 |
|  20.2500 |       3 |
|  24.7500 |       4 |
|  46.0000 |       5 |
|  20.7500 |       6 |
|  19.6667 |       7 |
+----------+---------+
8 rows in set (0.00 sec)
第二步:以上面这个结果与students表建立连接。
mariadb [hellodb]> select * from students,(select avg(age),classid from students group by classid) as avg_age where students.classid=avg_age.classid;
+-------+---------------+-----+--------+---------+-----------+----------+---------+
| stuid | name          | age | gender | classid | teacherid | avg(age) | classid |
+-------+---------------+-----+--------+---------+-----------+----------+---------+
|     1 | shi zhongyu   |  22 | m      |       2 |         3 |  36.0000 |       2 |
|     2 | shi potian    |  22 | m      |       1 |         7 |  20.5000 |       1 |
|     3 | xie yanke     |  53 | m      |       2 |        16 |  36.0000 |       2 |
|     4 | ding dian     |  32 | m      |       4 |         4 |  24.7500 |       4 |
|     5 | yu yutong     |  26 | m      |       3 |         1 |  20.2500 |       3 |
|     6 | shi qing      |  46 | m      |       5 |      null |  46.0000 |       5 |
|     7 | xi ren        |  19 | f      |       3 |      null |  20.2500 |       3 |
|     8 | lin daiyu     |  17 | f      |       7 |      null |  19.6667 |       7 |
|     9 | ren yingying  |  20 | f      |       6 |      null |  20.7500 |       6 |
|    10 | yue lingshan  |  19 | f      |       3 |      null |  20.2500 |       3 |
|    11 | yuan chengzhi |  23 | m      |       6 |      null |  20.7500 |       6 |
|    12 | wen qingqing  |  19 | f      |       1 |      null |  20.5000 |       1 |
|    13 | tian boguang  |  33 | m      |       2 |      null |  36.0000 |       2 |
|    14 | lu wushuang   |  17 | f      |       3 |      null |  20.2500 |       3 |
|    15 | duan yu       |  19 | m      |       4 |      null |  24.7500 |       4 |
|    16 | xu zhu        |  21 | m      |       1 |      null |  20.5000 |       1 |
|    17 | lin chong     |  25 | m      |       4 |      null |  24.7500 |       4 |
|    18 | hua rong      |  23 | m      |       7 |      null |  19.6667 |       7 |
|    19 | xue baochai   |  18 | f      |       6 |      null |  20.7500 |       6 |
|    20 | diao chan     |  19 | f      |       7 |      null |  19.6667 |       7 |
|    21 | huang yueying |  22 | f      |       6 |      null |  20.7500 |       6 |
|    22 | xiao qiao     |  20 | f      |       1 |      null |  20.5000 |       1 |
|    23 | ma chao       |  23 | m      |       4 |      null |  24.7500 |       4 |
+-------+---------------+-----+--------+---------+-----------+----------+---------+
23 rows in set (0.00 sec)
第三步:这里就直接作判断就可以了。
mariadb [hellodb]> select * from students,(select avg(age) as avg_age_col,classid from students group by classid) as avg_age_tab where students.classid=avg_age_tab.classid and age > avg_age_col order by students.classid;
+-------+---------------+-----+--------+---------+-----------+-------------+---------+
| stuid | name          | age | gender | classid | teacherid | avg_age_col | classid |
+-------+---------------+-----+--------+---------+-----------+-------------+---------+
|     2 | shi potian    |  22 | m      |       1 |         7 |     20.5000 |       1 |
|    16 | xu zhu        |  21 | m      |       1 |      null |     20.5000 |       1 |
|     3 | xie yanke     |  53 | m      |       2 |        16 |     36.0000 |       2 |
|     5 | yu yutong     |  26 | m      |       3 |         1 |     20.2500 |       3 |
|    17 | lin chong     |  25 | m      |       4 |      null |     24.7500 |       4 |
|     4 | ding dian     |  32 | m      |       4 |         4 |     24.7500 |       4 |
|    11 | yuan chengzhi |  23 | m      |       6 |      null |     20.7500 |       6 |
|    21 | huang yueying |  22 | f      |       6 |      null |     20.7500 |       6 |
|    18 | hua rong      |  23 | m      |       7 |      null |     19.6667 |       7 |
+-------+---------------+-----+--------+---------+-----------+-------------+---------+
9 rows in set (0.00 sec)
mariadb [hellodb]>
再来一个:要疯了。这个我这样写总觉得有点复杂了。不知道大家有没有简略点的。
如何显示其成员数最少为3个的班级的同学中年龄大于同班同学平均年龄的同学?
mariadb [hellodb]> select sql_no_cache * from (select avg(age) as a,classid from students where classid in (select classid from students group by classid having count(*) >= 3) group by classid) as s,students where students.classid=s.classid and age > a;
+---------+---------+-------+---------------+-----+--------+---------+-----------+
| a       | classid | stuid | name          | age | gender | classid | teacherid |
+---------+---------+-------+---------------+-----+--------+---------+-----------+
| 20.5000 |       1 |     2 | shi potian    |  22 | m      |       1 |         7 |
| 36.0000 |       2 |     3 | xie yanke     |  53 | m      |       2 |        16 |
| 24.7500 |       4 |     4 | ding dian     |  32 | m      |       4 |         4 |
| 20.2500 |       3 |     5 | yu yutong     |  26 | m      |       3 |         1 |
| 20.7500 |       6 |    11 | yuan chengzhi |  23 | m      |       6 |      null |
| 20.5000 |       1 |    16 | xu zhu        |  21 | m      |       1 |      null |
| 24.7500 |       4 |    17 | lin chong     |  25 | m      |       4 |      null |
| 19.6667 |       7 |    18 | hua rong      |  23 | m      |       7 |      null |
| 20.7500 |       6 |    21 | huang yueying |  22 | f      |       6 |      null |
+---------+---------+-------+---------------+-----+--------+---------+-----------+
9 rows in set (0.00 sec)
mariadb [hellodb]>
有人说mysql中对子查询的优化不好,所以子查询也要少用。
3、联合查询:
把两个或多个查询语句的结果合并起来。union
这个简单,就是一个结果附加在了另一个结果的下面。叠加起来了。
select name,age from teachers union select name,age from students;
把后面的语句结果连接在前面结果的下面。
union 可以有多个,可以连接多个查询结果。
各个查询结果的字段数要相同。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product