mysql学习笔记

本文详细介绍了SQL的基础操作,包括新增、删除、修改和查询数据,以及条件筛选、排序、函数应用和分组查询。讲解了如何使用INSERT、DELETE、UPDATE、SELECT语句,以及WHERE、ORDER BY、GROUP BY、HAVING等关键字。还探讨了子查询、联合查询、分页和数据控制语言(DCL)中的权限管理。示例中展示了如何在学生表和教师表中进行各种操作,以及如何进行数据库权限分配。
摘要由CSDN通过智能技术生成

SQL基础

操作的是表中的数据信息

写入信息

数据库中的信息发生了真实的改变

​ 新增( insert ) 删除( delete ) 修改( update )

读取信息

数据库中的信息没有发生改变,只是将数据展示出来也成为DQL语言

​ 查询( select )

一、基本写法

1.新增语句

列名和值一一对应

insert into tableName(列名,列名...) values(,...)

如果想要新增的记录是表的全部列,可以省略表名后面的列名

但要求values 后面值的个数及类型必须与表中列的顺序、类型、个数一致

insert into tableName values(,...)

一次新增多条

insert into tableName values(,...),(,...)

将查询的记录添加新增到表,前提是查询出来的列的数据类型、个数、顺序都要与被新增的表一致

insert into tableName select * from tableName;

补充

默认创建的数据库,字符集有默认值( latin1 ), 那么当前数据库中的所有表的字符集都会按照这个字符集处理,不能存储中文

create database test default character set = 'utf8';

2.删除语句

delete from tableName;

3.修改语句

update tableName set=;
-- 修改多条
update tableName set=,=;

4.查询语句

select 列名,列名 from tableName;
-- 查询所有列
select * from tableName;

二、条件筛选 + 排序

1. where

  1. where是一个关键字,拼接在除了insert语句以外的其他语句基本结构之后
delete from tableName where ......
update tableName set=where......
select * from tableName where......
  1. where用来筛选出符合条件的记录行数( 不是控制显示的列 )
  2. 按照某一个列或者是某一些条件筛选( 列一定满足条件 )
  3. where 条件后面具体怎么使用 连接什么东西
    1. 比较运算符 > >= < <= != =

    2. 算数运算符 + - * /

    3. 逻辑运算符 and or not

      优先级 and > or > not

    4. between and( 认为这是一个条件 )

      在什么和什么之间( 闭区间 )

      not between and ( 不在这之间的 )

    5. in( 满足一个或多个 )

    6. like ( 像什么一样的 ) 模糊查询

      %:用来代替0-n个字符

      _:用来代替1个字符( 有且只有一个 )

创建一个学生表,用来记录学生信息
学号	名字	性别	年龄	生日	语文	英语	物理	体育	班级编号
create table student(
	sid int(15),
	sname varchar(10),
	ssex varchar(4),
	sage int(3),
	sbirthday date,
	chinese float(5,2), -- (5,2)代表总共可以存储5位数字,小数点之后有两位
	english float(5,2),
	physics float(5,2),
	physical float(5,2),
	classid int(4)
);
insert into student values(1,'zhangsan','nan',22,'2000-01-01',98,95,89,92,1);
insert into student values(2,'lisi','nan',22,'2000-02-05',92,93,85,96,1);
insert into student values(3,'wangwu','nv',22,'2000-01-04',98,84,73,87,2);
insert into student values(4,'zhaoliu','nan',20,'2002-03-03',99,90,89,94,2);
insert into student values(5,'qianqi','nv',20,'2002-02-02',76,88,67,94,3);
insert into student values(6,'wangjiu','nv',21,'2001-01-01',80,75,86,62,3);
insert into student values(7,'wushi','nan',21,'2001-01-01',98,99,99,98,3);
-- 查询语文成绩满足99分的
select * from student where chinese > 95;
-- 查询英语成绩小于等于85分的
select * from student where english <= 85;
-- 查询体育成绩等于99分的
select * from student where physical = 99;
-- 查询两年后年龄超过23岁的
select * from student where sage + 2 > 23;
-- 查询语文成绩在95分以上且英语成绩95以上的
select * from student where chinese >= 95 and english >= 95;
-- 执行这条sql, 数据库底层大致做的事
-- 1. 解析sql
-- 2. 从表中将全部数据读取出来,放到数据库缓存
-- 3. 将缓存的数据拿出来循环遍历,每一次拿到一行记录 与 where条件作比较
--    假设表中7条记录,如果只写一个where条件 执行7次循环就可以比较出来
--    如果and连接不止一个条件 先按第一个条件筛选 然后按照第二个条件筛选
-- 查询所有的性别为nan的或者20岁的
select * from student where ssex = 'nan' or sage = 20;
-- 查询物理成绩在85到到75之间的
select * from student where physics between 75 and 85;
select * from student where physics >= 75 and physics <= 90;
-- 查询语文成绩99和92的
select * from student where chinese = 99 or chinese = 92;
select * from student where chinese in(99,92);
-- 查询语文成绩除了99和92以外的
select * from student where chinese not in(99,92);
-- 查询姓名是以z开头的
select * from student where sname like 'z%';
-- 查询姓名里面带n的
select * from student where sname like '%n%';
-- 查询姓名里面不带n的
select * from student where sname not like '%n%';
-- 删除姓名为wangwu的
delete from student where sname = 'wangwu';
-- 把lisi的性别改为nv
update student set ssex = 'nv' where sname = 'lisi';

2. 排序

连接在查询语句之后

order by 列

asc ( 升序排列 ) desc ( 降序排列 )

-- 按照语文成绩降序排列
select * from student order by chinese desc;
-- 年龄大于20的 然后按照英语升序排列
select * from student where sage > 20 order by english asc;
-- order by 不写升序和降序 默认是升序排列
select * from student order by english;
-- 按照语文成绩降序 且英语升序排列
select * from student order chinese desc, english asc;

三、函数

函数可以放置在什么位置

  1. 放置在列

    select 函数() from tableName;
    
  2. 放在条件筛选的后面

    selectfrom tableName where sal > 函数()
    

也可以参考文件夹中的《MySQL常用的函数.pdf》

1.聚合函数

distinct( 去重复 )

distinct 列( 如果列有一样的数据,将一样的是数据合并,合并之后的数据行数会减少 所以查询的每一个列,他的行数和个数需要一致)
-- 对性别去重
select distinct ssex from student;
-- sutdent 表中性别是有重复的
-- 如果要对ssex去重
select sname,distinct ssex from suudent;-- 能这样写不?
-- 名字没有重复的,每个人对应一个sex,如果按照上面的查询,查询出来的结果会剩下几个( 原数据有7条 )
-- 但是sname查出来有7条,ssex distinct之后只有2条记录( 那么这样写能行吗? )
-- 这肯定不行 因为行数对应不上了
select distinct ssex,sname from student;
-- 两个列的位置互换一下 那么可以这样写不?
-- 查出来的结果却是7行记录
-- 因为 distinct 会将两个列作为一个整体,如果这个整体的数据一致了,他才会去重复
1.分组函数

count() max() min() avg() sum()

-- 查询表中有多少条数据
select count(*) from student;
-- 查询语文分数最高的
select max(chinese) from student;
-- 查询英语的平均值
select avg(english) from student;
-- 对英语分数求和
select sum(english) from student;
-- 分组函数, 但是上面的sql并没有分组, 那么mysql会把整张表当作一个组

分组函数 + 分组条件

分组条件( group by 列)

-- 查询表中每个班级有多少人
select classid,count(sid) from student group by classid;
-- 按照性别分组 ,查看不同性别人数
select ssex,count(sid) from student group by ssex;
-- 查询每个年龄有多少人
select sage,count(sid) from student group by sage;
-- 查询表中每个班级的语文平均分
select classid,avg(chinese) from student group by classid;
-- 按照每个班级的语文平均分 升序排列
select classid,avg(chinese) from student group by classid order by avg(chinese);-- 如果不写别名
-- 查询表中所有的nan同学, 看看哪个班级有男同学
-- 先进行条件筛选 后分组
select classid from student where ssex = 'nan' group by classid;
-- 查询表中所有的20岁的同学,看看他们都在哪个班级,并有多少人
select classid,count(*) from student where sage = 20 group by classid;
-- 查询表中语文平均成绩高于90分的班级
-- 先分组 后拿平均成绩条件筛选
-- where group by order by 如果同时出现
-- 他们的优先级是 where > group by > order by

-- 所以 select classid from student group by classid where avg(chinese) > 90; 这种写法当然不行的啦!
-- (查询表中语文平均成绩高于90分的班级) 所以这个想要查询出来的话,逻辑上就必须要先分组,分组之后才能条件筛选
-- 所以这个时候,mysql 提供了新的关键字
-- having
-- having 的使用与where类似,都是做条件筛选的
select classid from student group by classid having avg(chinese) > 90;
所以 分组条件 + 分组函数的查询需要考虑几个问题
	1.在查询之前需要考虑到底是先分组,还是先筛选
	  先筛选 后分组 where + group by
	  先分组 后筛选 group by + having
	2.因为在查询的时候一旦分组,那么行数就会减少,所以想要看到的数据的个数需要与分组条件的个数一致

四、嵌套

1个完整的sql语句中,嵌套了另一个完整的sql语句

-- 查询表中语文成绩最高的人
-- 正常逻辑讲 select * from student where chinese = 最高
-- 但是最高分是多少并不知道 所以能够知道这个最高分是多少就能查出最高分的那个人了
-- 换句话来说 能查到最高分就行了
-- 最高分怎么查?
select max(chinese) from student;-- 这条语句的结果就是最高分
-- 那么将这个结果当做条件 就能查出来最高分的那个人
select * from student where chinese = (select max(chinese) from student);

嵌套可以将一个查询的结果当做条件再次查询

可以将查询的最终结果当做一张新表,在新表的基础上再次查询

-- 如果想要把嵌套以后的结果当做一张表来处理,那么需要给这张表取一个别名
select * from( select sname,ssex,sage,classid from student ) newtable;

新建一张城市表( 每个班级对应一个城市 )
create table myclass(
	classid int(4),
	classname varchar(10),
	classloc varchar(15)
);

insert into myclass values(1,'classone','beijing');

insert into myclass values(2,'classtwo','shenzhen');

insert into myclass values(3,'classthree','hangzhou');
-- 查询在深圳班级上课的同学有哪些
-- 我们要查的是同学 是不是应该先把同学查出来 而同学表中只有一个班级编号
-- 那么是不是应该满足这个条件
-- select * from student where classid = 深圳班级编号
select * from student where classid = (select classid from myclass where classioc = 'shenzhen')

五、关键字的使用

这些关键字都是在子集范围内查询的

in() -- 括号中的可以理解为子集

1. in

满足查询子集中的某一个即可( 默认 = 比较 )

in后面的子集内可以是常量,也可以是另一条sql语句查询出来的结果
-- 查询出1班和3班的同学
select * from student where classid in(1,3)
-- 查询出在beijing和hanghzou班级上课的同学
select * from student where classid in(select classid from myclass where classioc in('beijing','hangzhou'));
-- 通过beijing和hanghzhou两个地名确认班级,然后在到学生表里确定beijng和hangzhou上课的同学
-- 查询不在beijing上课的同学 如果不知道beijing的班级编号那么就只能嵌套了
select * from student where classid not in(select classid from myclass where classioc = 'beijing')

2. any some all

这三个关键字使用起来与in类似,查询是否满足子集中的条件,但关键字的后面不允许写固定值( 只允许写sql语句 )

select * from student where classid >any (select classid from myclass where classid > 1);
-- 意思就是 满足any中的条件的其中一个就行,大于1 那么就只能查出来2班和三班,any什么意思,表示这里面满足其中的一个即可,那这个sql查出来的就只有3班的同学 因为大于嘛,any可以是 > 也可以是 <,而in默认是等于,any相对于in要更灵活,any也可以是等 =( 等价与in )
-- some 与any完全一致
select * from student where classid >some (select classid from myclass where classid > 1);
all ( 满足查询子集的全部才可以 )
> all  < all  = all
select * from student where classid > all( select classid from myclass where  classid > 1)
-- classid > 1的结果是2和3 
-- 那么这个sql的意思就是 student 中的classid 必须要大于2 且大于3
-- 必须两个条件同时满足才行

3. union

集合操作( 并集 ) 将两个子元素的结果合并到一起

两张表---> student、teacher
学校想要召开运动会( 老师和学生都会参与 )
参加比赛的同学是运动员,非运动员的同学是不是也要做点看台上加油之类的事
非运动员的同学是不是也要服装整齐一点
学校想要给所有的老师和同学都准备统一的服装
那么这时候是不是要统计全学校所有的老师和学生的信息
这时候就需要将老师的信息和学生的信息都查出来 成一张新的表,这个表交给做衣服的人
也就是说,这个时候需要将学生和老师的信息竖着连成一张表
所以这里就需要用到union了

create table teacher(
	tid int(11),
	tname varchar(12),
	tsex varchar(4),
	tbirthday date
);
insert into teacher values(1,'zjq1','nan',1999-07-01),(2,'zjq2','nv',1999-07-01),(3,'zjq3','nan',1999-07-01);

-- 查询每一个人的编号、名字、性别( 为了简便,表里就没加身高体重了,嘿嘿 )
select tid,tname,tsex from teacher
union
select sid,sname,ssex from student;
那么 合并有没有什么要求?
比如说 老师查了3个列,学生查了4个列,这样行不行?
列数不一样 是不行的,即使上面那个sql列多也不行
使用union的要求
1. 要求前后两个查询子集的列数是一致
2. 拼接后显示的列名是前一个子集默认的列名
3. 类型没有要求
4. 注意 union和union all的区别
	union 会在合并结果集之后做去重的处理 性能较慢
		如果产生重复数据,记录的是第一次找到的那条数据
	union all 是将两个结果的子集直接合并 不做任何处理	

六、联合查询

分为 等值连接、外连接、内连接

有两个地区的球队参加比赛
a地区有4支球队,b地区有3支球队
比赛采取的是循环赛制,己方的所有球队与对方的所有球队都要进行一场比赛
两方的球队 就是乘积关系 4*3=12 最后一共有12场比赛
这个比赛的过程,我们称为笛卡尔积
CREATE TABLE `dept` ( -- 部门表
  `DEPTNO` int(4) NOT NULL,
  `DNAME` varchar(14) DEFAULT NULL,
  `LOC` varchar(13) DEFAULT NULL,
  PRIMARY KEY (`DEPTNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `dept` VALUES ('10', 'ACCOUNTING', 'NEW YORK');
INSERT INTO `dept` VALUES ('20', 'RESEARCH', 'DALLAS');
INSERT INTO `dept` VALUES ('30', 'SALES', 'CHICAGO');
INSERT INTO `dept` VALUES ('40', 'OPERATIONS', 'BOSTON');
-----------------------------------------------------

CREATE TABLE `emp` ( -- 员工表
  `EMPNO` int(4) NOT NULL,
  `ENAME` varchar(10) DEFAULT NULL,
  `JOB` varchar(9) DEFAULT NULL,
  `MGR` int(4) DEFAULT NULL,
  `HIREDATE` date DEFAULT NULL,
  `SAL` float(7,2) DEFAULT NULL,
  `COMM` float(7,2) DEFAULT NULL,
  `DEPTNO` int(4) DEFAULT NULL,-- 部门编号
  PRIMARY KEY (`EMPNO`),
  KEY `FK_DEPTNO` (`DEPTNO`) USING BTREE,
  CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`DEPTNO`) REFERENCES `dept` (`DEPTNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `emp` VALUES ('7369', 'SMITH', 'CLERK', '7902', '1980-12-17', '800.00', null, '20');
INSERT INTO `emp` VALUES ('7499', 'ALLEN', 'SALESMAN', '7698', '1981-02-20', '1600.00', '300.00', '30');
INSERT INTO `emp` VALUES ('7521', 'WARD', 'SALESMAN', '7698', '1981-02-22', '1250.00', '500.00', '30');
INSERT INTO `emp` VALUES ('7566', 'JONES', 'MANAGER', '7839', '1981-04-02', '2975.00', null, '20');
INSERT INTO `emp` VALUES ('7654', 'MARTIN', 'SALESMAN', '7698', '1981-09-28', '1250.00', '1400.00', '30');
INSERT INTO `emp` VALUES ('7698', 'BLAKE', 'MANAGER', '7839', '1981-05-01', '2850.00', null, '30');
INSERT INTO `emp` VALUES ('7782', 'CLARK', 'MANAGER', '7839', '1981-06-09', '2450.00', null, '10');
INSERT INTO `emp` VALUES ('7788', 'SCOTT', 'ANALYST', '7566', '1987-04-19', '3000.00', null, '20');
INSERT INTO `emp` VALUES ('7839', 'KING', 'PRESIDENT', null, '1981-11-17', '5000.00', null, '20');
INSERT INTO `emp` VALUES ('7844', 'TURNER', 'SALESMAN', '7698', '1981-09-08', '1500.00', '0.00', '30');
INSERT INTO `emp` VALUES ('7876', 'ADAMS', 'CLERK', '7788', '1987-05-23', '1100.00', null, '20');
INSERT INTO `emp` VALUES ('7900', 'JAMES', 'CLERK', '7698', '1981-12-03', '950.00', null, '30');
INSERT INTO `emp` VALUES ('7902', 'FORD', 'ANALYST', '7566', '1981-12-03', '3000.00', null, '20');
INSERT INTO `emp` VALUES ('7934', 'MILLER', 'CLERK', '7782', '1982-01-23', '1300.00', null, '10');
-- 将两张表的数据拼接在一块,可以采用笛卡尔积的方式
-- 查询 所有的员工加上员工所对应的部门的信息
-- 拼一起的效果就是 列的个数是两个表之和
-- 横着的行的个数是两个表乘积
select * from emp,dept;
-- 这个操作,mysql会把emp的每一行记录当做一个整体,dept的,每一行记录当做一个整体,然后无条件的拼一起
-- 这个sql执行完的结果 叫做笛卡尔积
-- 但是会发现一个问题 每一个员工都对应着4个部门,但是只有一个才有意义( deptno ),这个编号应该要跟部门的编号对应上 两个列的值对应上才有意义

1.等值连接

因为两张表相连 产生了大量的无意义的数据
在笛卡尔积的基础上 进行条件筛选
select * from emp,dept where deptno = deptno;
-- 按照这种写法,我们可能懂意思,但是mysql不一定懂啊
-- 所以需要将他们区分开
select * from emp,dept where emp.deptno = dept.deptno;
-- 通常来讲,筛选都是靠等号来连接的 所以将他称之为等值连接
-- 注意:如果两张表有列名一致,那么需要加前缀( 哪张表的列 )
-- 对于笛卡尔积 没有关系的两张表 也能连接

2.外连接

select * from a left/right join b on 条件

left 和 right 是干嘛的,a和b又影响着什么?

1.两张表 a和b 他们取决于谁的数据在左边显示,a先出现 所以a先显示 b 后出现所以 b在右边显示。
2. left 和 right来控制哪张表的数据作为基准
   作为基准的表的数据会全部显示出来,非基准的表按照on条件拼接
   若找到条件拼接,则正常显示,若找不到满足条件的则以null显示
   left 和 right 性能比笛卡尔积快	
select * from emp e left join dept d on e.deptno = d.deptno;

3.内连接

只要能匹配上的,匹配不上的都不要

select * from a inner join b on 条件

-- emp 有个mgr列( 表示员工的经理编号 )
-- 我想在左边显示员工,然后后面不显示编号,显示那个人的名是谁
select e1.empno,e1.ename,e1.magr,e2.empno,e2.ename from emp e1 
inner join emo e2 on e1.mgr = e2.empno;

设计表关系如下
	国家(Country)
	国家cid(主键) 国家名称cname  
	 1             中国
	 2             美国
	 3             日本
	地区表(Area)
	地区aid(主键) 地区名称aname 国家cid
	  1             北方           1
	  2             南方           1
	  3             西部           2
	  4             东部           2
	  5             北海道         3
	  6             四国           3
	城市表(City)
	城市cityid(主键)  城市名称cityname  人口数量citysize   地区aid
	   1                哈尔滨           750               1
	   2                大连             50                1
	   3                北京             2000              1
	   4                上海             1500              2
	   5                杭州             800               2
	   6                洛杉矶           1200              3
	   7                休斯顿           750               3
	   8                纽约             1000              4
	   9                底特律           500               4
	   10               东京             1500              5
	   11               名古屋           50                5
	   12               大阪             20                6   
	------------------------------------------------------------
创建表
create table country(
	cid int(4),
	cname varchar(20)
) character set utf8;	
insert into country values(1,'中国'),(2,'美国'),(3,'日本');
-----------------------------------------------------
create table area(
	aid int(4),
	aname varchar(20),
	cid int(4)
) character set utf8;		
insert into area values (1,'北方',1),
                        (2,'南方',1),
                        (3,'西部',2),
                        (4,'东部',2),
                        (5,'北海道',3),
                        (6,'四国',3);	
--------------------------------------------------------	
create table city(
	cityid int(4),
	cityname varchar(20),
	citysize int(10),
	aid int(4)
) character set utf8;	
insert into city values(1,'哈尔滨',750,1),(2,'大连',50,1),
					   (3,'北京',2000,1),(4,'上海',1500,2),
					   (5,'杭州',800,2),(6,'洛杉矶',1200,3),
					   (7,'休斯顿',750,3),(8,'纽约',1000,4),
					   (9,'底特律',500,4),(10,'东京',1500,5),						   (11,'名古屋',50,5),(12,'大阪',20,6);	
	
	1.查询人口数在1000到2000之间的城市所属在哪个地区
	2.查询每个国家的城市个数 按照城市个数升序排列
	3.查询各地区城市人口平均数 按照人口平均数降序排列
	4.查询哈尔滨所在的国家的名字
	5.查询各地区名字和人口总数 
	6.查询美国有哪些城市 列出城市名
	7.查询人口最多的城市在哪个国家
	8.查询每个国家的人口总数
	9.查询城市人口数为1500万的国家名字
	10.查询各地区总人数 按照人口数总量降序排列
	11.查询人口总数超过5000的国家名称
	12.查询人口数大于杭州的城市都有哪些
-- 1.查询人口数在1000到2000之间的城市所属在哪个地区?
select a.aname from area a inner join city ci on a.aid = c.aid
where ci.citysize between 1000 and 2000 group by a.aname;
-- 2.查询每个国家的城市个数 按照城市个数升序排列
select c.cname,count(ci.cityid) '城市个数' from country c
inner join area a on a.cid = c.cid 
inner join city ci on ci.aid = a.aid
group by c.cname
order by `城市个数` asc;
-- 3.查询各地区城市人口平均数 按照人口平均数降序排列
select a.aname,avg(ci.citysize) ag from area a 
inner join city ci on a.aid = ci.aid
group by a.aname order by ag desc;
-- 4.查询哈尔滨所在的国家的名字
select c.cname from country c 
inner join area a on c.cid = a.cid
inner join city ci on a.aid = ci.aid
where ci.cityname = '哈尔滨';
-- 5.查询各地区名字和人口总数
select a.aname,sum(ci.citysize) '总数' from area a 
inner join city ci on a.aid = ci.aid
group by a.aname
-- 6.查询美国有哪些城市 列出城市名
select ci.cityname from country c
inner join area a on a.cid = c.cid
inner join city ci on a.aid = ci.aid 
where c.cname = '美国';
-- 7.查询人口最多的城市在哪个国家
select c.cname from country c 
inner join area a on a.cid = c.cid
inner join city ci on a.aid = ci.aid
where ci.citysize = (select max(citysize) from city);
-- 8.查询每个国家的人口总数
select c.cname,sum(ci.citysize) '人口总数' from country c
inner area on c.cid = a.cid
inner city ci on a.aid = ci.aid
group by c.cname;
-- 9.查询城市人口数为1500万的国家名字
select c.cname from country c 
inner join area a on c.cid = a.cid
inner city ci on ci.aid = a.aid
where ci.citysize = 1500;
-- 10.查询各地区总人数 按照人口数总量降序排列
select a.aname,sum(ci.citysize) '人口数' from area a
inner join city ci on a.aid = ci.aid
group by a.aname order by `人口数` desc;
-- 11.查询人口总数超过5000的国家名称
select c.cname from country c 
inner join area a on c.cid = a.cid
inner join city ci on ci.aid = a.aid
group by c.cname having sum(ci.citysize) > 5000;
-- 12.查询人口数大于杭州的城市都有哪些
select cityname from city where citysize > 
(select citysize from city where cityname = '杭州');

七、行列互换

创建一个仓库 存储仓库的库存信息
create table warehouse(
	wname varchar(8),
	winventory int(8),
	wmonth varchar(8)
) character set utf8;
insert into warehouse values
('A',100,'一月份'),('B',1000,'一月份'),('C',10,'一月份'),
('A',200,'二月份'),('B',2000,'二月份'),('C',20,'二月份'),
('A',300,'三月份'),('B',3000,'三月份'),('C',30,'三月份');

此时warehouse表中是

wname   winventory  wmonth
 A         100       一月份
 B         1000      一月份
 C         10        一月份
 A         200       二月份
 B         2000      二月份
 C         20        二月份
 A         300       三月份
 B         3000      三月份
 C         30        三月份
 
 但是我想展示成这种效果
 仓库名称   一月份   二月份   三月份 
	A       100     200     300		
    B       1000    2000    3000	
	C       10      20      30

想要达到这种效果,里面肯定会用到分组 或者是去重复 但是呢distinct 并没有做
任何的分析,只是单纯的把重复的去掉了,所以distinct 肯定不好用。
那么 我们可以先写个sql放在这里
select from warehouse group by 仓库名称
我们知道,一旦使用了分组条件,可以显示的列只有两种
一种是分组条件,一种是分组函数
所以 第一个列肯定是仓库名称 
select 仓库名称, from warehouse group by 仓库名称
后面的列呢,要么是分组条件,要么是分组函数
但是,我们要的是月份里的值所以值肯定不能count
max呢
select 仓库名称,max() from warehouse group by 仓库名称
当然max里面显示的肯定不是一个最大值,里面每一个值都是需要判断的
我们显示的列是4个,仓库名称已经有了,但只有两个列
select 仓库名称,max(),max(),max() from warehouse group by 仓库名称
我们就套三个max,关键是这些值是什么 每个组里面都有个一月份
所以加个判断max(判断 月份=1 显示库存)
这个值放到max里面,其实没有什么影响,因为每一组中都只有一个值( 月份对应的库存 )
所以这个地方不一定非要写max,写min也行
就可以写成这样
select 
    仓库名称,
    max(判断 月份=1 显示库存),
    max(判断 月份=2 显示库存),
    max(判断 月份=3 显示库存) 
from warehouse 
group by 仓库名称;
if函数
if(表达式,v1,v2)如果表达式满足显示v1,否则显示v2

select 
wname '仓库名称',
max(if(wmonth = '一月份',winventory,0)) '1月份',
max(if(wmonth = '二月份',winventory,0)) '2月份',
max(if(wmonth = '二月份',winventory,0)) '3月份'
from warehouse
group by wname;

八、分页( limit )

-- 换表了  -->emp
-- 按照员工的工资排序
select * from emp order by sal desc;
-- 现在,我想每一页中只显示5行 记录
-- 分页
-- mysql里面有个关键字叫做limit
-- 这个关键字放在哪儿的,放在整个查询的后面
-- 查询完后,对结果分页
limit a,b;
-- a代表的是想要显示的起始行的索引( 从0开始 ) 包括此行, 也可以叫偏移量
-- b表示的是想要显示的行数 比如一页想显示5行,那个b给5 limit a,5;
select * from emp order by sal desc limit 0,5;

DCL数据控制语言

Data Control Language

控制用户的权限

​ grant 赋予

​ remove 回收

前提是 我们拥有的账号是一个SYSDBA管理员 root
管理员可以操作其他普通用户的权限
通过root账号可以看到mysql.user表
user表中记录着所有的用户信息
user列(用户的账号)  host列( 指的是能够在哪一个ip下操作 ) 
-- 1.创建一个新账户
create user '用户名'@'ip' identified by '密码';-- 基本写法
create user 'zjq'@'localhost' identified by '123456';
-- 这里注意,账户创建成功以后 默认只有一个权限 只能登录 Usage

-- 查看用户的权限
show grants for '用户名'@'ip';
show grants for 'zjq'@'localhost';

-- 2.给用户赋予权限
grants '权限' on 数据库名.to '用户名'@'ip';
-- 比如 想给用户所有数据库的所有表的所有权限
grants all on *.* to 'zjq'@'localhost';
-- 赋予权限之后最好刷新一下
flush privileges;

-- 3.回收用户的权限( 回收不了Usage )
revoke 权限 on 数据库名.from '用户名'@'ip';
revoke all on *.* from 'zjq'@'localhost';

-- 4.修改用户的密码
-- mysql 5.7 以后只有 authentication_string列 做了加密处理
update user set authentication_string = password('1234') where user = zjq;

-- 5.删除用户
drop user '用户'@'ip';

本文章部分知识点来源于 渡一教育

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值