Mysql多表查询, 视图,事务,索引,函数,go连接数据库

1.1 今日目标

  1. 理解多表查询
  2. 理解子查询
  3. 能够创建视图
  4. 能够删除视图
  5. 能够查看创建视图的SQL语句
  6. 能够理解事务的作用
  7. 能够操作事务
  8. 理解索引的作用
  9. 能够创建索引
  10. 能够删除索引
  11. 知道常用的函数
  12. 了解预处理语句的作用
  13. 能够使用预处理语句
  14. 了解存储过程的作用
  15. 能够创建存储过程
  16. 能够调用存储过程
  17. 能够通过Go语言连接MySQL数据库
  18. 能够通过Go语言对MySQL进行增、删、改、查的操作

1.2 多表查询分类

测试代码

/*stu测试数据*/
create table stu
(
    stuNo char(6) primary key,
    stuName varchar(10) not null,
    stuSex char(2) not null,
    stuAge tinyint not null ,
    stuSeat tinyint not null,
    stuAddress varchar(10) not null,
    ch tinyint,
    math tinyint 
);


insert into stu values ('s25301','张秋丽','男',18,1,'北京',80,null);
insert into stu values ('s25302','李文才','男',31,3,'上海',77,76);
insert into stu values ('s25303','李斯文','女',22,2,'北京',55,82);
insert into stu values ('s25304','欧阳俊雄','男',28,4,'天津',null,74);
insert into stu values ('s25305','诸葛丽丽','女',23,7,'河南',72,56);
insert into stu values ('s25318','争青小子','男',26,6,'天津',86,92);
insert into stu values ('s25319','梅超风','女',23,5,'河北',74,67);

insert into stu values ('s25320','Tom','男',24,8,'北京',65,67);
insert into stu values ('s25321','Tabm','女',23,9,'河北',88,77);

/*stuinfo测试数据*/
create table stuinfo
(
    stuNo char(6) primary key,
    stuName varchar(10) not null,
    stuSex char(2) not null,
    stuAge tinyint not null ,
    stuSeat tinyint not null,
    stuAddress varchar(10) not null
);


insert into stuinfo values ('s25301','张秋丽','男',18,1,'北京');
insert into stuinfo values ('s25302','李文才','男',31,3,'上海');
insert into stuinfo values ('s25303','李斯文','女',22,2,'北京');
insert into stuinfo values ('s25304','欧阳俊雄','男',28,4,'天津');
insert into stuinfo values ('s25305','诸葛丽丽','女',23,7,'河南');
insert into stuinfo values ('s25318','争青小子','男',26,6,'天津');
insert into stuinfo values ('s25319','梅超风','女',23,5,'河北');

/*stuMarks测试数据*/

create table stuMarks
(
examNo char(7) primary key,
stuNo char(6) not null ,
writtenExam int,
labExam int
);

insert into stumarks values ('s271811','s25303',80,58);
insert into stumarks values ('s271813','s25302',50,90);
insert into stumarks values ('s271815','s25304',65,50);
insert into stumarks values ('s271816','s25301',77,82);
insert into stumarks values ('s271819','s25318',56,48);
insert into stumarks values ('s271820','s25320',66,77);

将多个表的数据横向的联合起来。
1、 内连接
2、 外连接
a) 左外连接
b) 右外连接
3、 交叉连接
4、 自然连接

1.2.1 内连接【inner join】---获取两个表的公共部分

语法一:select 列名 from 表1 inner join 表2 on 表1.公共字段=表2.公共字段

语法二:select 列名 from 表1,表2 where 表1.公共字段=表2.公共字段

例题

--方法一:
 select stuname,stusex,writtenexam,labexam from stuinfo inner join stumarks on stuinfo.stuno=stumarks.stuno;
+----------+--------+-------------+---------+
| stuname  | stusex | writtenexam | labexam |
+----------+--------+-------------+---------+
| 李斯文        | 女      |          80 |      58 |
| 李文才        | 男       |          50 |      90 |
| 欧阳俊雄        | 男       |          65 |      50 |
| 张秋丽         | 男       |          77 |      82 |
| 争青小子        | 男       |          56 |      48 |
+----------+--------+-------------+---------+

--方法二:
select stuinfo.stuno,stuname,stusex,writtenexam,labexam from stuinfo,stumarks where stuinfo.stuno=stumarks.stuno;
+--------+----------+--------+-------------+---------+
| stuno  | stuname  | stusex | writtenexam | labexam |
+--------+----------+--------+-------------+---------+
| s25303 | 李斯文        | 女      |          80 |      58 |
| s25302 | 李文才        | 男       |          50 |      90 |
| s25304 | 欧阳俊雄        | 男       |          65 |      50 |
| s25301 | 张秋丽         | 男       |          77 |      82 |
| s25318 | 争青小子        | 男       |          56 |      48 |
+--------+----------+--------+-------------+---------+

--可以给表取别名
 select i.stuno,stuname,stusex,writtenexam,labexam from stuinfo i,stumarks s where i.stuno=s.stuno;
+--------+----------+--------+-------------+---------+
| stuno  | stuname  | stusex | writtenexam | labexam |
+--------+----------+--------+-------------+---------+
| s25303 | 李斯文        | 女      |          80 |      58 |
| s25302 | 李文才        | 男       |          50 |      90 |
| s25304 | 欧阳俊雄        | 男       |          65 |      50 |
| s25301 | 张秋丽         | 男       |          77 |      82 |
| s25318 | 争青小子        | 男       |          56 |      48 |
+--------+----------+--------+-------------+---------+
5 rows in set (0.00 sec)

脚下留心:显示公共字段需要指定表名


思考:
select * from 表1 inner join 表2 on 表1.公共字段=表2.公共字段 和
select * from 表2 inner join 表1 on 表1.公共字段=表2.公共字段 结果是否一样?
答:一样的,因为内连接获取的是两个表的公共部分

多学一招:三个表的内连接如何实现?
select * from 表1 inner join 表2 on 表1.公共字段=表2.公共字段inner join 表3 on 表2.公共字段=表3.公共字段

1.2.2 左外连接【left join】

以左边的表为标准,如果右边的表没有对应的记录,用NULL填充。

语法:select 列名 from 表1 left join 表2 on 表1.公共字段=表2.公共字段

例题

select stuname, writtenexam, labexam from stuinfo left join stumarks on stuinfo.stuno=stumarks.stuno;
+--------------+-------------+---------+
| stuname      | writtenexam | labexam |
+--------------+-------------+---------+
| 李斯文       |          80 |      58 |
| 李文才       |          50 |      90 |
| 欧阳俊雄     |          65 |      50 |
| 张秋丽       |          77 |      82 |
| 争青小子     |          56 |      48 |
| 诸葛丽丽     |        NULL |    NULL |
| 梅超风       |        NULL |    NULL |
+--------------+-------------+---------+
7 rows in set (0.00 sec)

思考:
select * from 表1 left join 表2 on 表1.公共字段=表2.公共字段

select * from 表2 left join 表1 on 表1.公共字段=表2.公共字段 是否一样?
答:不一样,左连接一左边的表为准。

1.2.3 右外连接【right join】

以右边的表为标准,如果左边的表没有对应的记录,用NULL填充。

语法:select 列名 from 表1 right join 表2 on 表1.公共字段=表2.公共字段

例题

 select stuname, writtenexam, labexam from stuinfo right join stumarks on stuinfo.stuno=stumarks.stuno;
+--------------+-------------+---------+
| stuname      | writtenexam | labexam |
+--------------+-------------+---------+
| 李斯文       |          80 |      58 |
| 李文才       |          50 |      90 |
| 欧阳俊雄     |          65 |      50 |
| 张秋丽       |          77 |      82 |
| 争青小子     |          56 |      48 |
| NULL         |          66 |      77 |
+--------------+-------------+---------+
6 rows in set (0.00 sec)

思考:
select * from 表1 left join 表2 on 表1.公共字段=表2.公共字段

select * from 表2 right join 表1 on 表1.公共字段=表2.公共字段 是否一样?

答:一样的

1.2.4 交叉连接【cross join】

插入测试数据

 create table t1(
    -> id int,
    -> name varchar(10)
    -> );
Query OK, 0 rows affected (0.06 sec)

 insert into t1 values (1,'tom'),(2,'berry');
Query OK, 2 rows affected (0.00 sec)

 create table t2(
    -> id int,
    -> score int);
Query OK, 0 rows affected (0.02 sec)

 insert into t2 values (1,88),(2,99);

1、如果没有连接表达式返回的是笛卡尔积

 select * from t1 cross join t2;   -- 返回笛卡尔积
+------+-------+------+-------+
| id   | name  | id   | score |
+------+-------+------+-------+
|    1 | tom   |    1 |    88 |
|    2 | berry |    1 |    88 |
|    1 | tom   |    2 |    99 |
|    2 | berry |    2 |    99 |
+------+-------+------+-------+

2、如果有连接表达式等价于内连接

 select * from t1 cross join t2 where t1.id=t2.id;
+------+-------+------+-------+
| id   | name  | id   | score |
+------+-------+------+-------+
|    1 | tom   |    1 |    88 |
|    2 | berry |    2 |    99 |
+------+-------+------+-------+

1.2.5 自然连接【natural】

自动的判断连接条件,它是过同名字段来判断的

自然连接又分为:

  1. 自然内连接 natural join
  2. 自然左外连接 natural left join
  3. 自然右外连接 natural right join

例题:
自然内连接:

 select * from stuinfo natural join stumarks;  -- 自然内连接
+--------+--------------+--------+--------+---------+------------+---------+-------------+---------+
| stuNo  | stuName      | stuSex | stuAge | stuSeat | stuAddress | examNo  | writtenExam | labExam |
+--------+--------------+--------+--------+---------+------------+---------+-------------+---------+
| s25303 | 李斯文       | 女     |     22 |       2 | 北京       | s271811 |          80 |      58 |
| s25302 | 李文才       | 男     |     31 |       3 | 上海       | s271813 |          50 |      90 |
| s25304 | 欧阳俊雄     | 男     |     28 |       4 | 天津       | s271815 |          65 |      50 |
| s25301 | 张秋丽       | 男     |     18 |       1 | 北京       | s271816 |          77 |      82 |
| s25318 | 争青小子     | 男     |     26 |       6 | 天津       | s271819 |          56 |      48 |
+--------+--------------+--------+--------+---------+------------+---------+-------------+---------+
5 rows in set (0.00 sec)

自然左外连接:

 select * from stuinfo natural left join stumarks; --自然左外连接
+--------+--------------+--------+--------+---------+------------+---------+-------------+---------+
| stuNo  | stuName      | stuSex | stuAge | stuSeat | stuAddress | examNo  | writtenExam | labExam |
+--------+--------------+--------+--------+---------+------------+---------+-------------+---------+
| s25303 | 李斯文       | 女     |     22 |       2 | 北京       | s271811 |          80 |      58 |
| s25302 | 李文才       | 男     |     31 |       3 | 上海       | s271813 |          50 |      90 |
| s25304 | 欧阳俊雄     | 男     |     28 |       4 | 天津       | s271815 |          65 |      50 |
| s25301 | 张秋丽       | 男     |     18 |       1 | 北京       | s271816 |          77 |      82 |
| s25318 | 争青小子     | 男     |     26 |       6 | 天津       | s271819 |          56 |      48 |
| s25305 | 诸葛丽丽     | 女     |     23 |       7 | 河南       | NULL    |        NULL |    NULL |
| s25319 | 梅超风       | 女     |     23 |       5 | 河北       | NULL    |        NULL |    NULL |
+--------+--------------+--------+--------+---------+------------+---------+-------------+---------+
7 rows in set (0.00 sec)

自然右外连接

 select * from stuinfo natural right join stumarks;  --自然右外连接
+--------+---------+-------------+---------+--------------+--------+--------+---------+------------+
| stuNo  | examNo  | writtenExam | labExam | stuName      | stuSex | stuAge | stuSeat | stuAddress |
+--------+---------+-------------+---------+--------------+--------+--------+---------+------------+
| s25303 | s271811 |          80 |      58 | 李斯文       | 女     |     22 |       2 | 北京       |
| s25302 | s271813 |          50 |      90 | 李文才       | 男     |     31 |       3 | 上海       |
| s25304 | s271815 |          65 |      50 | 欧阳俊雄     | 男     |     28 |       4 | 天津       |
| s25301 | s271816 |          77 |      82 | 张秋丽       | 男     |     18 |       1 | 北京       |
| s25318 | s271819 |          56 |      48 | 争青小子     | 男     |     26 |       6 | 天津       |
| s25320 | s271820 |          66 |      77 | NULL         | NULL   |   NULL |    NULL | NULL       |
+--------+---------+-------------+---------+--------------+--------+--------+---------+------------+
6 rows in set (0.00 sec)

自然连接结论:

  1. 表连接通过同名的字段来连接的

  2. 如果没有同名的字段返回笛卡尔积

  3. 会对结果进行整理,整理的规则如下
    a) 连接字段保留一个

    b) 连接字段放在最前面

    c) 左外连接左边在前,右外连接右表在前

1.2.6 using()

  1. 用来指定连接字段。

  2. using()也会对连接字段进行整理,整理方式和自然连接是一样的。

 select * from stuinfo inner join stumarks using(stuno);   -- using指定字段
+--------+----------+--------+--------+---------+------------+---------+-------------+---------+
| stuNo  | stuName  | stuSex | stuAge | stuSeat | stuAddress | examNo  | writtenExam | labExam |
+--------+----------+--------+--------+---------+------------+---------+-------------+---------+
| s25303 | 李斯文        | 女      |     22 |       2 | 北京           | s271811 |          80 |
  58 |
| s25302 | 李文才        | 男       |     31 |       3 | 上海          | s271813 |          50 |
  90 |
| s25304 | 欧阳俊雄        | 男       |     28 |       4 | 天津           | s271815 |          65 |
     50 |
| s25301 | 张秋丽         | 男       |     18 |       1 | 北京           | s271816 |          77 |
    82 |
| s25318 | 争青小子        | 男       |     26 |       6 | 天津           | s271819 |          56 |
     48 |
+--------+----------+--------+--------+---------+------------+---------+-------------+---------+
5 rows in set (0.00 sec)

1.3 子查询

语法

语法:select 语句 where 条件 (select … from 表)
  1. 外面的查询称为父查询,括号中的查询称为子查询
  2. 子查询为父查询提供查询条件

1.3.1 例题

1、查找笔试80分的学生

 select * from stuinfo where stuno=(select stuno from stumarks where writtenexam=80);
+--------+-----------+--------+--------+---------+------------+
| stuNo  | stuName   | stuSex | stuAge | stuSeat | stuAddress |
+--------+-----------+--------+--------+---------+------------+
| s25303 | 李斯文    | 女     |     22 |       2 | 北京       |
+--------+-----------+--------+--------+---------+------------+
1 row in set (0.00 sec)

2、查找笔试最高分的学生

--方法一:
select * from stuinfo where stuno=(select stuno from stumarks order by writtenexam desc limit 0,1);
+--------+-----------+--------+--------+---------+------------+
| stuNo  | stuName   | stuSex | stuAge | stuSeat | stuAddress |
+--------+-----------+--------+--------+---------+------------+
| s25303 | 李斯文    | 女     |     22 |       2 | 北京       |
+--------+-----------+--------+--------+---------+------------+
1 row in set (0.02 sec)




-- 方法二:

select * from stuinfo where stuno=(select stuno from stumarks where writtenexam=(select max(writtenexam) from stumarks));
+--------+-----------+--------+--------+---------+------------+
| stuNo  | stuName   | stuSex | stuAge | stuSeat | stuAddress |
+--------+-----------+--------+--------+---------+------------+
| s25303 | 李斯文    | 女     |     22 |       2 | 北京       |
+--------+-----------+--------+--------+---------+------------+
1 row in set (0.02 sec)

脚下留心:上面的例题,子查询只能返回一个值。如果子查询返回多个值就不能用“=”了,需要用 in

1.3.2 in|not in子查询

用于子查询的返回结果多个值。

1、查找笔试成绩及格的同学

select * from stuinfo where stuno in (select stuno from stumarks where writtenexam >=60);
+--------+--------------+--------+--------+---------+------------+
| stuNo  | stuName      | stuSex | stuAge | stuSeat | stuAddress |
+--------+--------------+--------+--------+---------+------------+
| s25303 | 李斯文       | 女     |     22 |       2 | 北京       |
| s25304 | 欧阳俊雄     | 男     |     28 |       4 | 天津       |
| s25301 | 张秋丽       | 男     |     18 |       1 | 北京       |
+--------+--------------+--------+--------+---------+------------+
3 rows in set (0.02 sec)

2、查询不及格的同学

 select * from stuinfo where stuno in (select stuno from stumarks where writtenexam <60);
+--------+--------------+--------+--------+---------+------------+
| stuNo  | stuName      | stuSex | stuAge | stuSeat | stuAddress |
+--------+--------------+--------+--------+---------+------------+
| s25302 | 李文才       | 男     |     31 |       3 | 上海       |
| s25318 | 争青小子     | 男     |     26 |       6 | 天津       |
+--------+--------------+--------+--------+---------+------------+
2 rows in set (0.00 sec)

3、查询没有通过的同学(不及格,缺考)

 select * from stuinfo where stuno not in (select stuno from stumarks where writtenexam >=60);
+--------+--------------+--------+--------+---------+------------+
| stuNo  | stuName      | stuSex | stuAge | stuSeat | stuAddress |
+--------+--------------+--------+--------+---------+------------+
| s25302 | 李文才       | 男     |     31 |       3 | 上海       |
| s25305 | 诸葛丽丽     | 女     |     23 |       7 | 河南       |
| s25318 | 争青小子     | 男     |     26 |       6 | 天津       |
| s25319 | 梅超风       | 女     |     23 |       5 | 河北       |
+--------+--------------+--------+--------+---------+------------+
4 rows in set (0.02 sec)

1.3.3 exists和not exists

1、 如果有人笔试超过80分就显示所有的学生

select * from stuinfo where exists (select * from stumarks where writtenexam >=60);
+--------+--------------+--------+--------+---------+------------+
| stuNo  | stuName      | stuSex | stuAge | stuSeat | stuAddress |
+--------+--------------+--------+--------+---------+------------+
| s25301 | 张秋丽       | 男     |     18 |       1 | 北京       |
| s25302 | 李文才       | 男     |     31 |       3 | 上海       |
| s25303 | 李斯文       | 女     |     22 |       2 | 北京       |
| s25304 | 欧阳俊雄     | 男     |     28 |       4 | 天津       |
| s25305 | 诸葛丽丽     | 女     |     23 |       7 | 河南       |
| s25318 | 争青小子     | 男     |     26 |       6 | 天津       |
| s25319 | 梅超风       | 女     |     23 |       5 | 河北       |
+--------+--------------+--------+--------+---------+------------+
7 rows in set (0.00 sec)

2、 如果没有人超过80分就显示所有的学生

 select * from stuinfo where not exists (select * from stumarks where writtenexam>=80);

Empty set (0.02 sec)

1.3.4 子查询分类

1、标量子查询:子查询返回的结果就一个

2、列子查询:子查询返回的结果是一个列表

3、行子查询:子查询返回的结果是一行

例题:查询成绩最高的男生和女生

select * from stu where (stusex, ch) in (select stusex, max(ch) from stu group by stusex);
+--------+-----------+--------+--------+---------+------------+------+------+
| stuNo  | stuName   | stuSex | stuAge | stuSeat | stuAddress | ch   | math |
+--------+-----------+--------+--------+---------+------------+------+------+
| s25301 | 张秋丽    | 男     |     18 |       1 | 北京       |   88 | NULL |
| s25321 | Tabm      | 女     |     23 |       9 | 河北       |   88 |   77 |
+--------+-----------+--------+--------+---------+------------+------+------+

4、表子查询:子查询返回的结果当成一个表

例题:查询成绩最高的男生和女生

mysql> select stuname,stusex,ch from (select * from stu order by ch desc) as t group by stusex;
+----------+--------+------+
| stuname  | stusex | ch   |
+----------+--------+------+
| Tabm     | 女      |   88 |
| 争青小子        | 男       |   86 |
+----------+--------+------+

脚下留心:from后面是一个表,如果子查询的结果当成表来看,必须将子查询的结果取别名。

1.4 视图【view】

1、 视图是一张虚拟表,它表示一张表的部分或多张表的综合的结构。

2、 视图仅仅是表结构,没有表数据。视图的结构和数据建立在表的基础上。

1.4.1 创建视图

语法

create [or replace] view 视图的名称
as
    select语句

例题:

 create view vw_stu
    -> as
    -> select stuname,stusex,writtenexam,labexam from stuinfo inner join stumarks using(stuno);
Query OK, 0 rows affected (0.00 sec)

多学一招:因为视图是一个表结构,所以创建视图后,会在数据库文件夹中多一个与视图名同名的.frm文件

1.4.2 使用视图

视图是一张虚拟表,视图的用法和表的用法一样

 select * from vw_stu;
+----------+--------+-------------+---------+
| stuname  | stusex | writtenexam | labexam |
+----------+--------+-------------+---------+
| 李斯文        | 女      |          80 |      58 |
| 李文才        | 男       |          50 |      90 |
| 欧阳俊雄        | 男       |          65 |      50 |
| 张秋丽         | 男       |          77 |      82 |
| 争青小子        | 男       |          56 |      48 |
+----------+--------+-------------+---------+

 update vw_stu set writtenexam=88 where stuname='李斯文';
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

1.4.3 查看视图的结构

语法:
desc 视图名

例题

desc vw_stu;
+-------------+-------------+------+-----+---------+-------+
| Field       | Type        | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| stuname     | varchar(10) | NO   |     | NULL    |       |
| stusex      | char(2)     | NO   |     | NULL    |       |
| writtenexam | int(11)     | YES  |     | NULL    |       |
| labexam     | int(11)     | YES  |     | NULL    |       |
+-------------+-------------+------+-----+---------+-------+

1.4.4 查看创建视图的语法

语法:

show create view 视图名

例题

1.4.5 显示所有视图

 --方法一:
 show tables;
+------------------+
| Tables_in_itcast |
+------------------+
| stu              |
| stuinfo          |
| stumarks         |
| t1               |
| t2               |
| vw_stu           |

-方法二
 select table_name from information_schema.views;
+------------+
| table_name |
+------------+
| vw_stu     |
+------------+
1 row in set (0.05 sec)
+------------------+

--方法三
 show table status where comment='view' \G
*************************** 1. row ***************************
           Name: vw_stu
         Engine: NULL
        Version: NULL
     Row_format: NULL
           Rows: NULL
 Avg_row_length: NULL
    Data_length: NULL
Max_data_length: NULL
   Index_length: NULL
      Data_free: NULL
 Auto_increment: NULL
    Create_time: NULL
    Update_time: NULL
     Check_time: NULL
      Collation: NULL
       Checksum: NULL
 Create_options: NULL
        Comment: VIEW
1 row in set (0.00 sec)

1.4.6 更改视图

语法:

alter view 视图名
as
    select 语句

例题:

 alter view vw_stu
     as
     select * from stuinfo;
Query OK, 0 rows affected (0.00 sec)

1.4.7 删除视图

语法:

drop view [if exists] 视图1,视图2,…

例题

 drop view vw_stu;
Query OK, 0 rows affected (0.00 sec)

1.4.8 视图的作用

  1. 筛选数据,防止未经许可访问敏感数据
  2. 隐藏表结构
  3. 降低SQL语句的复杂度

1.4.9 视图的算法

场景:找出语文成绩最高的男生和女生
我们可以将子查询封装到视图中

 create view vw_stu
    -> as
    -> select * from stu order by ch desc;
Query OK, 0 rows affected (0.00 sec)

但是,结果和上面不一样

 select * from vw_stu group by stusex;
+--------+---------+--------+--------+---------+------------+------+------+
| stuNo  | stuName | stuSex | stuAge | stuSeat | stuAddress | ch   | math |
+--------+---------+--------+--------+---------+------------+------+------+
| s25301 | 张秋丽        | 男       |     18 |       1 | 北京           |   80 | NULL |
| s25303 | 李斯文       | 女      |     22 |       2 | 北京           |   55 |   82 |
+--------+---------+--------+--------+---------+------------+------+------+

原因:这是因为视图的算法造成的

1. merge:合并算法,将视图的语句和外层的语句合并后在执行。
2. temptable:临时表算法,将视图生成一个临时表,再执行外层语句
3. undefined:未定义,MySQL到底用merge还是用temptable由MySQL决定,这是一个默认的算法,一般视图都会选择merge算法,因为merge效率高。

解决:在创建视图的时候指定视图的算法

create algorithm=temptable view 视图名
as
    select 语句

指定算法创建视图

 create algorithm=temptable view vw_stu
    -> as
    ->  select * from stu order by ch desc;
Query OK, 0 rows affected (0.00 sec)

 select * from vw_stu group by stusex;   -- 结果是正确的
+--------+----------+--------+--------+---------+------------+------+------+
| stuNo  | stuName  | stuSex | stuAge | stuSeat | stuAddress | ch   | math |
+--------+----------+--------+--------+---------+------------+------+------+
| s25321 | Tabm     | 女      |     23 |       9 | 河北          |   88 |   77 |
| s25318 | 争青小子        | 男       |     26 |       6 | 天津           |   86 |   92 |
+--------+----------+--------+--------+---------+------------+------+------+

1.5 事务【transaction】

  1. 事务是一个不可分割的执行单元
  2. 事务作为一个整体要么一起执行,要么一起回滚

插入测试数据

create table bank(
    -> cardid char(4) primary key,
    -> money int
    -> );
Query OK, 0 rows affected (0.00 sec)

insert into bank values ('1001',1000),('1002',100);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

1.5.1 事务操作

开启事务:start transaction或begin [work]
提交事务:commit
回滚事务:rollback

例题:

 delimiter    //          --更改定界符为 "//"

 start transaction;         -- 开启事务
    -> update bank set money=money-100 where cardid='1001';
    -> update bank set money=money+100 where cardid='1002'  //
Query OK, 0 rows affected (0.00 sec)

 commit  //   --提交事务
 rollback  //    --回滚事务

思考:事务什么时候产生?什么时候结束?
答:开启的时候产生,提交事务或回滚事务都结束

脚下留心:只有innodb和BDB才支持事务,myisam不支持事务。

1.5.2 设置事务的回滚点

语法:

设置回滚点: savepoint 回滚点名
回滚到回滚点: rollback to 回滚点

例题:

start transaction;
Query OK, 0 rows affected (0.00 sec)

insert into bank values ('1003',1000);
Query OK, 1 row affected (0.00 sec)

savepoint aa;    -- 设置回滚点 aa
Query OK, 0 rows affected (0.00 sec)

insert into bank values ('1004',500);
Query OK, 1 row affected (0.00 sec)
 
savepoint bb;   -- 设置回滚点bb
Query OK, 0 rows affected (0.00 sec)
 
rollback to aa;    -- 回滚到aa点
Query OK, 0 rows affected (0.00 sec)

 commit;    --提交事务

 select * from bank ;
+--------+-------+
| cardid | money |
+--------+-------+
| 1001   |   800 |
| 1002   |   200 |
| 1003   |  1000 |
+--------+-------+

1.5.3 事务的特性(ACID)

  1. 原子性(Atomicity):事务是一个整体,不可以再分,要么一起执行,要么一起不执行。
  2. 一致性(Consistency):事务完成时,数据必须处于一致的状态。
  3. 隔离性(Isolation):每个事务都是相互隔离的
  4. 永久性(Durability):事务完成后,对数据的修改是永久性的。

1.6 索引【index】

索引的优点:查询速度快

索引的缺点:

  1. 增、删、改(数据操作语句)效率低了
  2. 索引占用空间

1.6.1 索引的类型

  1. 普通索引
  2. 唯一索引(唯一键)
  3. 主键索引:只要主键就自动创建主键索引,不需要手动创建。
  4. 全文索引,搜索引擎使用,MySQL不支持中文的全文索引,我们通过sphinx去解决中文的全文索引。

1.6.2 创建普通索引【create index】

语法:

create index [索引名] on 表名 (字段名)
alter table 表名 add index [索引的名称] (列名)

例题:

--创建索引方法一
create index ix_stuname on stuinfo(stuname);
Query OK, 0 rows affected (0.08 sec)
Records: 0  Duplicates: 0  Warnings: 0

-- 创建索引方法二
alter table stuinfo add index ix_address (stuaddress);
Query OK, 0 rows affected (0.08 sec)
Records: 0  Duplicates: 0  Warnings: 0

 --创建表的时候就添加索引
 create table emp(
    -> id int,
    -> name varchar(10),
    -> index ix_name (name)      --创建索引, 并命名为ix_name
    -> );
Query OK, 0 rows affected (0.00 sec)

1.6.3 创建唯一索引

语法一:create unique index 索引名 on 表名 (字段名)
语法二:alter table 表名 add unqiue [index] [索引的名称] (列名)
语法三:创建表的时候添加唯一索引,和创建唯一键是一样的。

例题

--方法一:
 create unique index UQ_stuname on stu(stuname);
Query OK, 0 rows affected (0.06 sec)
Records: 0  Duplicates: 0  Warnings: 0

-- 方法二:
 alter table stu add unique UQ_address (stuaddress);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

-- 方法三
 create table stu2(
    -> id int,
    -> name varchar(20),
    -> unique UQ_name(name)
    -> );
Query OK, 0 rows affected (0.01 sec)

1.6.4 删除索引

语法

drop index 索引名 on 表名

例题

 drop index ix_stuname on stuinfo;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

1.6.5 创建索引的指导原则

  1. 该列用于频繁搜索

  2. 改列用于排序

  3. 公共字段要创建索引

  4. 如果表中的数据很少,不需要创建索引。MySQL搜索索引的时间比逐条搜索数据的时间要长。

  5. 如果一个字段上的数据只有几个不同的值,改字段不适合做索引,比如性别。

1.7 函数

1.7.1 数字类

select rand();          -- 生成随机数
+---------------------+
| rand()              |
+---------------------+
| 0.18474003969201822 |
+---------------------+
1 row in set (0.00 sec)

select * from stuinfo order by rand();    --随机排序

select * from stuinfo order by rand() limit 2;    --随机抽两个学生
+--------+----------+--------+--------+---------+------------+
| stuNo  | stuName  | stuSex | stuAge | stuSeat | stuAddress |
+--------+----------+--------+--------+---------+------------+
| s25305 | 诸葛丽丽         | 女      |     23 |       7 | 河南           |
| s25304 | 欧阳俊雄        | 男       |     28 |       4 | 天津           |
+--------+----------+--------+--------+---------+------------+
2 rows in set (0.00 sec)

select round(3.5);     --四舍五入
+------------+
| round(3.5) |
+------------+
|          4 |
+------------+
1 row in set (0.00 sec)

select ceil(3.1);   -- 向上取整
+-----------+
| ceil(3.1) |
+-----------+
|         4 |
+-----------+
1 row in set (0.00 sec)

select floor(3.9);  --向下取整
+------------+
| floor(3.9) |
+------------+
|          3 |
+------------+
1 row in set (0.00 sec)

select truncate(3.1415926,3);   -- 截取数字
+-----------------------+
| truncate(3.1415926,3) |
+-----------------------+
|                 3.141 |
+-----------------------+
1 row in set (0.00 sec)

1.7.2 字符串类

select ucase('i am a boy!');        -- 转成大写
+----------------------+
| ucase('i am a boy!') |
+----------------------+
| I AM A BOY!          |
+----------------------+
1 row in set (0.00 sec)

select lcase('I Am A Boy!');        --转成小写
+----------------------+
| lcase('I Am A Boy!') |
+----------------------+
| i am a boy!          |
+----------------------+
1 row in set (0.00 sec)

select left('abcde',3);     -- 从左边开始截取,截取3个
+-----------------+
| left('abcde',3) |
+-----------------+
| abc             |
+-----------------+
1 row in set (0.00 sec)

select right('abcde',3);        -- 从右边开始截取,截取3个
+------------------+
| right('abcde',3) |
+------------------+
| cde              |
+------------------+
1 row in set (0.00 sec)

select substring('abcde',2,3);  --从第2个位置开始截取,截取3个(位置从1开始)
+------------------------+
| substring('abcde',2,3) |
+------------------------+
| bcd                    |
+------------------------+
1 row in set (0.00 sec)

 select concat('中国','上海');  --字符串相连
+-----------------------+
| concat('中国','上海')       |
+-----------------------+
| 中国上海                    |
+-----------------------+
1 row in set (0.00 sec)

select concat(stuname,'-',stusex) from stuinfo;  -- 将表中的姓名和性别连接起来
+----------------------------+
| concat(stuname,'-',stusex) |
+----------------------------+
| 张秋丽-男                          |
| 李文才-男                         |
| 李斯文-女                        |
| 欧阳俊雄-男                         |
| 诸葛丽丽-女                         |
| 争青小子-男                         |
| 梅超风-女                        |
+----------------------------+
7 rows in set (0.00 sec)

-- coalesce(字段1,字段2)  如果字段1不为空就显示字段1,否则,显示字段2

select stuname,coalesce(writtenexam,'缺考'),coalesce(labexam,'缺考') from stuinfo natural left join stumarks;   -- 将考试成绩为空的显示为缺考
+----------+------------------------------+--------------------------+
| stuname  | coalesce(writtenexam,'缺考')    | coalesce(labexam,'缺考')    |
+----------+------------------------------+--------------------------+
| 张秋丽         | 77                           | 82                       |
| 李文才        | 50                           | 90                       |
| 李斯文        | 88                           | 58                       |
| 欧阳俊雄        | 65                           | 50                       |
| 诸葛丽丽         | 缺考                            | 缺考                        |
| 争青小子        | 56                           | 48                       |
| 梅超风        | 缺考                            | 缺考                        |
+----------+------------------------------+--------------------------+

select length('锄禾日当午');     --字节长度
+----------------------+
| length('锄禾日当午')          |
+----------------------+
|                   10 |
+----------------------+
1 row in set (0.00 sec)

select char_length('锄禾日当午');        -- 字符个数
+---------------------------+
| char_length('锄禾日当午')          |
+---------------------------+
|                         5 |
+---------------------------+
1 row in set (0.00 sec)

1.7.3 时间类

select unix_timestamp();    --获取时间戳
+------------------+
| unix_timestamp() |
+------------------+
|       1537084508 |
+------------------+
1 row in set (0.00 sec)

select from_unixtime(unix_timestamp()); --将时间戳转成年-月-日 小时:分钟:秒的格式
+---------------------------------+
| from_unixtime(unix_timestamp()) |
+---------------------------------+
| 2018-09-16 15:55:56             |
+---------------------------------+
1 row in set (0.00 sec)

select now();       --获取当前日期时间
+---------------------+
| now()               |
+---------------------+
| 2018-09-16 15:57:04 |
+---------------------+
1 row in set (0.00 sec)

select year(now()) 年,month(now()) 月, day(now()) 日,hour(now()) 小,minute(now()) 分钟,second(now()) 秒;
+------+------+------+------+------+------+
| 年     | 月     | 日     | 小时   | 分钟     | 秒     |
+------+------+------+------+------+------+
| 2018 |    9 |   16 |   15 |   59 |   14 |
+------+------+------+------+------+------+
1 row in set (0.00 sec)

select dayname(now()) 星期,monthname(now()),dayofyear(now()) 本年的第几天;
+--------+------------------+--------------+
| 星期       | monthname(now()) | 本年的第几天           |
+--------+------------------+--------------+
| Sunday | September        |          259 |
+--------+------------------+--------------+
1 row in set (0.00 sec)

select datediff(now(),'2008-8-8');  -- 日期相减
+----------------------------+
| datediff(now(),'2008-8-8') |
+----------------------------+
|                       3691 |
+----------------------------+
1 row in set (0.00 sec)

select convert(now(),date),convert(now(),time); -- 将now()转成日期和时间
+---------------------+---------------------+
| convert(now(),date) | convert(now(),time) |
+---------------------+---------------------+
| 2018-09-16          | 16:07:24            |
+---------------------+---------------------+

select cast(now() as date),cast(now() as time);   -- 将now()转成日期和时间
+---------------------+---------------------+
| cast(now() as date) | cast(now() as time) |
+---------------------+---------------------+
| 2018-09-16          | 16:08:03            |
+---------------------+---------------------+
1 row in set (0.00 sec)

1.7.4 加密函数

select md5('root'), she('root')
+----------------------------------+------------------------------------------+
| md5('root')                      | sha('root')                              |
+----------------------------------+------------------------------------------+
| 63a9f0ea7bb98050796b649e85481845 | dc76e9f0c0006e8f919e0c515c66dbba3982f785 |
+----------------------------------+------------------------------------------+
1 row in set (0.00 sec)

1.7.5 判断函数

语法

if (表达式,值1,值2)

例题:

mysql> select if(10%2=0,'偶数','奇数');
+--------------------------+
| if(10%2=0,'偶数','奇数')        |
+--------------------------+
| 偶数                        |
+--------------------------+
1 row in set (0.00 sec)

-- 语文和数学都超过60分才通过
select stuname,ch,math,if(ch>=60 && math>=60,'通过','不通过') '是否通过' from stu;
+----------+------+------+----------+
| stuname  | ch   | math | 是否通过       |
+----------+------+------+----------+
| 张秋丽         |   80 | NULL | 不通过        |
| 李文才        |   77 |   76 | 通过        |
| 李斯文        |   55 |   82 | 不通过        |
| 欧阳俊雄        | NULL |   74 | 不通过        |
| 诸葛丽丽         |   72 |   56 | 不通过        |
| 争青小子        |   86 |   92 | 通过        |
| 梅超风        |   74 |   67 | 通过        |
| Tom      |   65 |   67 | 通过        |
| Tabm     |   88 |   77 | 通过        |
+----------+------+------+----------+
9 rows in set (0.00 sec)

1.8 预处理

预编译一次,可以多次执行。用来解决一条SQL语句频繁执行的问题。

预处理语句:prepare  预处理名字 from ‘sql语句’
执行预处理:execute  预处理名字 [using 变量]

例题一:

prepare stmt from 'select * from stuinfo';  --创建预处理, ' '必须要加
Query OK, 0 rows affected (0.00 sec)
Statement prepared

execute stmt;   -- 执行预处理
+--------+----------+--------+--------+---------+------------+
| stuNo  | stuName  | stuSex | stuAge | stuSeat | stuAddress |
+--------+----------+--------+--------+---------+------------+
| s25301 | 张秋丽         | 男       |     18 |       1 | 北京           |
| s25302 | 李文才        | 男       |     31 |       3 | 上海          |
| s25303 | 李斯文        | 女      |     22 |       2 | 北京           |
| s25304 | 欧阳俊雄        | 男       |     28 |       4 | 天津           |
| s25305 | 诸葛丽丽         | 女      |     23 |       7 | 河南           |
| s25318 | 争青小子        | 男       |     26 |       6 | 天津           |
| s25319 | 梅超风        | 女      |     23 |       5 | 河北          |
+--------+----------+--------+--------+---------+------------+
7 rows in set (0.00 sec)

例题二:传递参数

delimiter // 
prepare stmt from 'select * from stuinfo where stuno=?'  // -- ?是位置占位符
Query OK, 0 rows affected (0.00 sec)
Statement prepared

set  @id='s25301';       -- 变量以@开头,通过set给变量赋值
execute stmt using @id //  -- 执行预处理,传递参数
Query OK, 0 rows affected (0.00 sec)

+--------+---------+--------+--------+---------+------------+
| stuNo  | stuName | stuSex | stuAge | stuSeat | stuAddress |
+--------+---------+--------+--------+---------+------------+
| s25301 | 张秋丽        | 男       |     18 |       1 | 北京           |
+--------+---------+--------+--------+---------+------------+
1 row in set (0.00 sec)
脚下留心:
1、?是位置占位符
2、变量以@开头
3、通过set给变量赋值

例题三:传递多个参数

prepare stmt from 'select * from stuinfo where stusex=? and stuaddress=?'  //
Query OK, 0 rows affected (0.00 sec)
Statement prepared

set @sex='男';
set @addr='北京';
execute stmt using @sex,@addr //
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+--------+---------+--------+--------+---------+------------+
| stuNo  | stuName | stuSex | stuAge | stuSeat | stuAddress |
+--------+---------+--------+--------+---------+------------+
| s25301 | 张秋丽        | 男       |     18 |       1 | 北京           |
+--------+---------+--------+--------+---------+------------+
1 row in set (0.00 sec)

1.9 存储过程【procedure】

1.9.1 存储过程的优点

  1. 存储过程可以减少网络流量
  2. 允许模块化设计
  3. 支持事务

1.9.2 创建存储过程

语法:

create procedure 存储过程名(参数)
begin
    sql语句;
end //

脚下留心:由于过程中有很多SQL语句,每个语句的结束都要用(;)结束。默认情况下,分号既表示语句结束,又表示向服务器发送SQL语句。我们希望分号仅表示语句的结束,不要将SQL语句发送到服务器执行,通过delimiter来更改结束符。

例题

delimiter //
 create procedure proc()     -- 创建存储过程
     begin
     select * from stuinfo;
     end //
Query OK, 0 rows affected (0.00 sec)

1.9.3 调用存储过程

语法:

call 存储过程名()

例题:

call proc() //     -- 调用存储过程
+--------+----------+--------+--------+---------+------------+
| stuNo  | stuName  | stuSex | stuAge | stuSeat | stuAddress |
+--------+----------+--------+--------+---------+------------+
| s25301 | 张秋丽         | 男       |     18 |       1 | 北京           |
| s25302 | 李文才        | 男       |     31 |       3 | 上海          |
| s25303 | 李斯文        | 女      |     22 |       2 | 北京           |
| s25304 | 欧阳俊雄        | 男       |     28 |       4 | 天津           |
| s25305 | 诸葛丽丽         | 女      |     23 |       7 | 河南           |
| s25318 | 争青小子        | 男       |     26 |       6 | 天津           |
| s25319 | 梅超风        | 女      |     23 |       5 | 河北          |
+--------+----------+--------+--------+---------+------------+
7 rows in set (0.00 sec)

1.9.4 删除存储过程

语法

drop procedure [if exists] 存储过程名

例题:

drop procedure proc //    -- 删除存储过程
Query OK, 0 rows affected (0.00 sec)

1.9.5 查看存储过程的信息

show create procedure 存储过程名\G

例题

show create procedure proc \G
*************************** 1. row ***************************
           Procedure: proc
            sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `proc`()
begin
select * from stuinfo;
end
character_set_client: gbk
collation_connection: gbk_chinese_ci
  Database Collation: utf8_general_ci
1 row in set (0.00 sec)

1.7.6 显示所有的存储过程

mysql> show procedure status \G

1.9.7 存储过程的参数

存储过程的参数分为:输入参数(in)【默认】,输出参数(out),输入输出参数(inout)

存储过程不能使用return返回值,要返回值只能通过“输出参数”来向外传递值。

例题一:传递学号,获取对应的信息

 create procedure proc(in param varchar(10))   -- 输入参数
    -> select * from stuinfo where stuno=param //
Query OK, 0 rows affected (0.00 sec)

call proc('s25301') //
+--------+---------+--------+--------+---------+------------+
| stuNo  | stuName | stuSex | stuAge | stuSeat | stuAddress |
+--------+---------+--------+--------+---------+------------+
| s25301 | 张秋丽        | 男       |     18 |       1 | 北京           |
+--------+---------+--------+--------+---------+------------+
1 row in set (0.00 sec)

例题二:查找同桌

 create procedure proc(name varchar(10))
     begin
     declare seat tinyint;   -- 声明局部变量
     select stuseat into seat from stuinfo where stuname=name;  -- 将座位号保存到变量中
     select * from stuinfo where stuseat=seat+1 or stuseat=seat-1;  -- 查找同桌
     end //
Query OK, 0 rows affected (0.00 sec)

call proc('李文才') //
+--------+----------+--------+--------+---------+------------+
| stuNo  | stuName  | stuSex | stuAge | stuSeat | stuAddress |
+--------+----------+--------+--------+---------+------------+
| s25303 | 李斯文        | 女      |     22 |       2 | 北京           |
| s25304 | 欧阳俊雄        | 男       |     28 |       4 | 天津           |
+--------+----------+--------+--------+---------+------------+
2 rows in set (0.00 sec)

强调

1、通过declare关键字声明局部变量;全局变量@开头就可以了
2、给变量赋值有两种方法
    方法一:set 变量名=值
    方法二:select 字段 into 变量 from 表 where 条件
3、声明的变量不能与列名同名

例题三:输出参数

create procedure proc(num int, out result int)  //out 表示输出参数
     begin
     set result=num*num;
     end //
Query OK, 0 rows affected (0.00 sec)

call proc(10,@result) //
Query OK, 0 rows affected (0.00 sec)

select @result //
+---------+
| @result |
+---------+
|     100 |
+---------+
1 row in set (0.00 sec)

例题四:输入输出参数

 create procedure proc(inout num int)  #  inout 表示是输入输出参数
     begin
     set num=num*num;
     end //
Query OK, 0 rows affected (0.00 sec)

    set @num=10;
    call proc(@num);
    select @num //
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+------+
| @num |
+------+
|  100 |
+------+
1 row in set (0.00 sec)

1.10 GO连接MySQL---windows

  1. 因为Go语言没有提供任何官方数据库驱动,所以需要安装第三方函数库。
  2. 由于在github上安装,所以需要安装git软件,安装过程一直点击下一步即可。安装完成后需要配置环境变量

1.10.1 安装git

git软件

安装完毕后,配置git的环境变量,这样可以使用get的指令

1.10.2 安装数据库驱动

设置GOPATH的环境变量,这样驱动才会下载到项目根目录中。


在cmd命令窗口中输入如下命令安装驱动

go get github.com/go-sql-driver/mysql

这一命令会从代码中获取驱动的具体代码,并将这些代码放置到包库中,当需要用到驱动的时候,编译器会把驱动代码与用户编写的代码一同编译。

安装完毕后,会在GOPATH下看到下载的驱动

1.10.3 连接数据库

1、在src目录下创建demo.go文件,导入数据库驱动

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

注意:程序在操作数据库的时候只需要用到database/sql,而不需要直接使用数据库驱动,所以程序在导入数据库驱动的时候将这个包的名字设置成下划线。

2、通过sql.open()连接数据库

sql.open(驱动名,数据源dsn)(*DB,err)

数据源语法:"用户名:密码@[连接方式](主机名:端口号)/数据库名"

注意:open()在执行时不会真正的与数据库进行连接,只是设置连接数据库需要的参数
ping()方法才是连接数据库

3、执行SQL语句

​ 创建测试表

mysql> create table stu(
    -> id int primary key,
    -> name varchar(10)
    -> );
Query OK, 0 rows affected (0.02 sec)

操作数据

package main

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "fmt"
)

func main(){
    //"用户名:密码@[连接方式](主机名:端口号)/数据库名"
    db,_:=sql.Open("mysql","root:root@(127.0.0.1:3306)/itcast") // 设置连接数据库的参数
    defer db.Close()    //关闭数据库
    err:=db.Ping()      //连接数据库
    if err!=nil{
        fmt.Println("数据库连接失败")
        return
    }

    //操作一:执行数据操作语句
    /*
    sql:="insert into stu values (2,'berry')"
    result,_:=db.Exec(sql)      //执行SQL语句
    n,_:=result.RowsAffected(); //获取受影响的记录数
    fmt.Println("受影响的记录数是",n)
    */

    //操作二:执行预处理
    /*
    stu:=[2][2] string{{"3","ketty"},{"4","rose"}}
    stmt,_:=db.Prepare("insert into stu values (?,?)")      //获取预处理语句对象
    for _,s:=range stu{
        stmt.Exec(s[0],s[1])            //调用预处理语句
    }
    */

    //操作三:单行查询
    /*
    var id,name string
    rows:=db.QueryRow("select * from stu where id=4")   //获取一行数据
    rows.Scan(&id,&name)        //将rows中的数据存到id,name中
    fmt.Println(id,"--",name)
    */

    //操作四:多行查询
    rows,_:=db.Query("select * from stu")       //获取所有数据
    var id,name string
    for rows.Next(){        //循环显示所有的数据
        rows.Scan(&id,&name)
        fmt.Println(id,"--",name)
    }
}

1.11 作业

1、 显示地区及每个地区参加考试的人数,并按人数降序排列。

select stuaddress,count(writtenexam) c from stuinfo left join stumarks using(stuno) group by stuaddress order by c desc;

2、 显示有学生参加考试的地区

方法一:过滤

select stuaddress,count(writtenexam) c from stuinfo left join stumarks using(stuno) group by stuaddress having c>0;

方法二:链接查询

select distinct stuaddress c from stuinfo right join stumarks using(stuno) ;

3、 显示男生和女生的人数

方法一:

select stusex,count() from stuinfo where stusex='男' union select stusex,count() from stuinfo where stusex='女';

方法二:

select sum(stusex='男') 男,sum(stusex='女') 女 from stuinfo;

4、 显示每个地区的男生和女生和总人数

select stuaddress,count(stusex) 总人数, sum(stusex='男') 男,sum(stusex='女') 女 from stuinfo group by stuaddress
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 转 # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    吕品㗊阅读 9,695评论 0 44
  • 一、MySQL架构与历史 A.并发控制 1.共享锁(shared lock,读锁):共享的,相互不阻塞的。 2.排...
    阿休阅读 4,633评论 0 37
  • Mysql概述 数据库是一个易于访问和修改的信息集合。它允许使用事务来确保数据的安全性和一致性,并能快速处理百万条...
    彦帧阅读 13,653评论 10 461
  • 阳光洒落 点亮橱窗微渺尘埃 窗外黑白斑马线 多少人来来往往 衣冠整齐,眼眉低垂 像遗失了玩具的孩子 走不出伤悲 大...
    燕纯阅读 340评论 0 1
  • 【人生百态】底层|目录上一章 【人生百态】底层(25)李国前求学 这个时候,国家在旗里成立了一个国家粮食储备库,主...
    雪狐狸阅读 745评论 0 0