mysql总结-sql总结
Mysql操作
系统命令
连接MYSQL:
mysql -h主机地址 -u用户名 -p用户密码
连接到本机上的MYSQL
mysql -uroot -p
超级用户root是没有密码的,故直接回车即可进入到MYSQL中了
连接远程机上的mysql
mysql -h110.110.110.110 -uroot -pabcd123
修改密码:
mysqladmin -u用户名 -p旧密码 password 新密码
查看链接信息
show status like '%connect%';
Aborted_connects 尝试连接到MySQL服务器失败的次数,
Threads_connected 当前打开的连接的数量
Connections 表示MySQL从启动至今,成功建立连接的连接数,这个值是不断累加的。
max_connect_errors 允许单用户连接错误最大值,超过后在不刷新状态的情况下,禁止该用户新连接
max_connections 实例最大连接数限制
max_user_connections 但用户连接最大限制,默认0表示无限制
connect_timeout 用户连接超时限制,超过10秒,如果依旧无法连接到mysql,则终止连接
查看timeout设置
show variables like '%timeout%';
单位是秒
connect_timeout:tcp连接超时是时间(默认10秒),是连接过程中握手的超时时间,是客户端与mysql服务器建立连接时,握手开始到结束的超时时间。
interactive_timeout/wait_timeout:交互/非交互模式下的不活跃线程(sleep状态)的等待时间,默认8小时,连接超过这个时间长度没有过操作,mysql会断开该连接。
修改wait_timeout:
set global wait_timeout=864000;
查看连接线程参数
show variables like 'thread%';
thread_cache_size 设置连接线程缓存的数目。这个缓存相当于MySQL线程的缓存池
thread_handling 默认值是: one-thread-per-connection 表示为每个连接提供或者创建一个线程来处理请求,直至请求完毕,连接销毁或者存入缓存池。当值是no-threads 时,表示在始终只提供一个线程来处理连接,一般是单机做测试使用的。
thread_stack stack 是堆的意思
thread_concurrency 参数用于向操作系统建议期望的并发线程数,mysql 5.6后不再使用
查看正在执行的sql进程
show processlist

在info列可以查看执行的sql
如果要终止某个操作
kill 指定的id
数据库操作
创建数据库:
CREATE DATABASE 数据库名;
CREATE DATABASE IF NOT EXISTS RUNOOB DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
删除数据库
drop database <数据库名>;
选择数据库
USE database_name;
查询当前数据库名称
SELECT DATABASE();
添加索引
ALTER TABLE `student` ADD INDEX `idx_age` (`age`);
alter table table_name add unique index uniq_name1_name2 (`column1`,`column2`);
删除索引
ALTER TABLE `your_table_name` DROP INDEX `idx_age`;
创建表
CREATE TABLE `user` (
`name` varchar(5) NOT NULL,
`age` int(11) NOT NULL,
`createtime` datetime DEFAULT NULL,
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
修改表
添加字段:
ALTER TABLE mp_qualification ADD COLUMN third_code varchar(255) NOT NULL COMMENT '活动币活动编码';
ALTER TABLE mp_qualification ADD COLUMN third_code varchar(255) NOT NULL COMMENT '活动币活动编码' after second_code; -- 指定新字段放在谁后面
修改列类型:
ALTER TABLE 表名 MODIFY 列名 列的新类型
如果被修改的列中已存在数据,那么列的新类型会影响已存在的数据;
修改列名称:
ALTER TABLE 表名 CHANGE 原列 名新列名 列类型;或者alter table student1 change column 列名 新列名 列类型;
删除列:
ALTER TABLE 表名 DROP 列名;
修改表名:
ALTER TABLE 表名 RENAME TO新表名(to可以省略)。或RENAME TABLE 表名 TO新表名
修改表的字符集:
ALTER TABLE 表名 character set utf8;
修改表注释:
alter table test1 comment '修改后的表的注释';
修改表的auto_increment
alter table <tableName> auto_increment = <num>;
删除表
drop table 表名;为了防止删除一个不存在的表而报错
使用:drop table if exists 表名
查看表的定义信息
SHOW CREATE TABLE mytable;
插入数据
向表中插入数据有以下三种方式:
insert into students values(4,'aaaa',1,1);
insert into students set sid=5,sname='ddd',gender=2,dept_id=1;
insert into students select * from students_bak;
insert into student(number,name) values(‘xxx’,’xxx’)
insert into 表名(列名1,列名2, ...) values(列值1, 列值2, ...),(列值1, 列值2, ...)
修改数据
根据条件修改
update student set age=18 where name=’wangwu’ or number=’itcast_0002’;
update student set age=age+1 where age>=15 and age<=35;
交换两个字段的值
UPDATE student SET a1 = (@temp := a1), a1 = a2, a2 = @temp;
update配合select
UPDATE t_trade td , t_order od SET td.park_id=od.park_id WHERE td.order_code = od.order_code;
删除数据
DELETE FROM 表名 [WHERE 条件];
TRUNCATE TABLE 表名;
delete和truncate区别
delete可以根据条件进行删除数据
delete会把删除操作作为事务记录在日志中,以便进行回滚
delete不清除自增记录数
truncate直接销毁表并重新新建表,不会记录删除到日志,不能回滚,会清除自增记录数
当表被truncate 后,这个表和索引所占用的空间会恢复到初始大小,delete操作不会减少表或索引所占用的空间。
查询
分页查询
取出sql表中第31开始查询10条
select * from t order by id limit 30,10;
distinct查询
查询指定列值不同的记录
select distinct sname from emp;
查询多个字段都不重复的记录(也就是多个字段都相同的记录会去除)
select distinct sname,deptno from emp;
加减乘除查询
(如果有一列为null,则结果为null;非数值类型的列做运算时,它的值都会被当做0来计算)
select ename,sal,sal*1.5 from emp;
select ename,sal,comm,sal+comm from emp;
条件查询
select * from table1 where name=’zhangsan’;
select * from emp where deptno=20;
select * from emp where sal>20000;
#between查询两端的值都在查找范围内
select * from emp where sal between 20000 and 30000;
select * from emp where comm is not null;
select * from emp where job in(‘经理’,’分析师’);
模糊查询
#“%”表示匹配0到N个字符
select * from emp where ename like ‘张%’;
#包含指定字符的就会被查到
select * from stu where sname like ‘%刚%’
#一个“_”匹配一个字符
select * from emp where ename like ‘__’;
使用‘张%’能够用到索引,‘%刚%’和‘%刚’都不能用到索引,当该字段没有建立索引时就没什么关系了
排序查询
不能依赖mysql默认的排序,不一定按照插入的顺序
默认升序asc,如果要倒序desc
select * from emp order by sal
先根据一个字段排序,该字段相同时再按照第二个字段排序,依次可以有多个字段
select * from emp order by sal asc ,comm desc;
聚合查询
MySQL就为我们提供了一些聚合函数。常用的聚合函数有:MAX()、MIN()、COUNT()、SUM()、AVG()
COUNT()函数统计表中包含的记录行的总数,或根据查询结果返回列中包含的数据行数。其使用方法有两种:
①COUNT(*),计算表中总的行数,不管某列是否有数值或空值
②COUNT(字段名),计算指定列下总的行数,计算时将忽略空值的行
SUM()是一个求总和的函数,返回指定列值的总和。sum()函数在计算时,忽略列值为null的行。
AVG()函数通过计算返回的行数和每一行数据的和,求得指定列数据的平均值。
MAX()函数返回指定列中的最大值
MAX()函数除了用来找出最大的列值或日期值之外,还可以返回任意列中的最大值,返回包括字符类型的最大值。在堆字符类型数据进行比较时,按照字符的ASCII码值大小进行比较,从a~z,a的ASCII码最小,z的最大。在比较时,先比较第一个字母,如果相等,继续比较下一个字符,一直到两个字符不相等或字符结束为止。
select count(*) from student;
select sum(math) from student;
select avg(math) from student;
select max(math) from student;
select min(math) from student;
分组查询
group by 的特性是分组后会取同一组的第一个值
分组后每个相同分组字段只返回一条数据,可以用GROUP_CONCAT函数把想返回所有值组合成一个字符串返回
SELECT sex,GROUP_CONCAT(name) FROM employee GROUP BY sex;
:WHERE是对分组前记录的条件判断
select deptno,count(*) from emp where sal>15000 group by deptno;
在分组后再进行的条件判断需要使用另一个关键词:having。
select deptno,count(*) from emp where sal>15000 group by deptno having count(*)>2;
多个字段groupby
SELECT Subject, Semester, Count(*) FROM Subject_Selection GROUP BY Subject, Semester
对Subject_Selection表中的数据进行分组,将具有相同Subject和Semester字段值的记录放到同一个分组里去, 然后对每个分组中的数据应用聚合函数(COUNT,SUM, AVG,etc)。
group by 后面的字段顺序 只是影响了结果的顺序,不会影响结果的值。
带排序的group(是对group后的数据进行排序)
SELECT * from `user` GROUP BY age order by age;
对分组数量排序
SELECT order_code,count(order_code) c from t_trade WHERE create_time > '2021-06-18 00:00:00' GROUP BY order_code HAVING c>1 order by c desc
如何先排序再分组:
方法一,仅适用于低于5.7版本的MySql--
select * from (select * from shop order by price desc) a GROUP BY a.shop_name;
5.7版本后mysql优化时会优化掉这个子查询
方法二:使用join查询
这里id是唯一的,如果排序字段不是唯一的就外面在进行一次group by
SELECT a.* FROM USER a
JOIN (SELECT max(id) m FROM USER GROUP BY age ) b ON a.id = b.m
ORDER BY id DESC;
子表查询
字表必须定义别名才可以
SELECT id FROM(SELECT id,NAME FROM t1) b;
SELECT NAME FROM t1,(SELECT tid FROM t2 where t2.age>20) AS b WHERE b.tid=t1.id;
SELECT NAME n,(SELECT age FROM t1 WHERE n=NAME) AS b FROM t1 GROUP BY NAME;
select * from emp where sal>all(select sal from emp where deptno=30);
select * from emp where sal>any(select sal from emp where deptno=30);
select * from emp where (job,deptno,sal) in (select job,deptno,sal from emp where ename=’殷天正’);
all是与里面的数据每一个比较都都符合要求才行
any是与里面的数据比较有一个符合条件就行
关联查询和笛卡尔积
关联查询,首先都是进行笛卡尔积,然后根据连接条件和where条件进行条件过滤。
笛卡尔积:
假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。
到表里就是a表有5条记录,b表有6条记录,他们的笛卡尔积为5*6=30条数据
连接查询处理过程:
生成笛卡尔结果集,使用on条件去掉不符合的数据,添加left join或right join主表符合条件的数据,where条件筛选
如果是inner join没有添加outer join的过程
关联查询缺点:
关联查询会产生笛卡尔积,如果表数据量太多,效率就会下降,可以分别根据索引单表取数据,然后在程序里面合并处理
内连接
select e.ename,e.sal,d.dname from emp e inner join dept d on e.deptno=d.deptno;
方言:
select * from emp,dept where emp.deptno=dept.deptno;
两个表的结果数据都需要符合连接条件
外连接
外连接代表:主表查询的结果不受on的连接条件限制,连接表受连接条件的限制
左外连接的关键词是:LEFT OUTER JOIN或者 LEFT JOIN
SELECT * FROM 表1 别名1 LEFT OUTER JOIN 表2 别名2 ON 别名1.列名=别名2.列名
中表1就是左表,又称为主表,表2是右表。
SELECT A.* FROM A LEFT JOIN B ON (A.id = B.id) WHERE b.id IS NULL
右连接的关键词是:RIGHT OUTER JOIN或者 RIGHT JOIN
SELECT * FROM 表1 别名1 RIGHT OUTER JOIN 表2 别名2 ON 别名1.列名=别名2.列名
其中表1是左表,表2是右表,又称为主表。
UNION[ALL] 合并结果集
查询的两个结果集的列名称不需要相同,只要满足列的个数和类型一样就可以;右表查询出来的结果集会被合到最左边表中
个数和类型不一样查询会报错
select * from one union all select * from two
UNION,先获取到两个查询的结果集,再去除重复行;重复的行是指结果中每个属性都一样
UNION ALL,不去除重复行。
Exsists和not exsists
exists查询,如果子查询中结果有数据才会执行主查询,note exisists如果没结果才会执行主查询
select * from goods a where EXISTS(select cat_id from ecs_category b where a.cat_id = b.cat_id);
SELECT * FROM A WHERE NOT EXISTS ( SELECT 1 FROM B WHERE B.id = A.id );
case when
case when语句,用于计算条件列表并返回多个可能结果表达式之一。
CASE 具有两种格式:简单 CASE 函数将某个表达式与一组简单表达式进行比较以确定结果。 CASE 搜索函数计算一组布尔表达式以确定结果。 两种格式都支持可选的 ELSE 参数。
- -搜索Case函数:
Case函数(Case搜索函数): 判断表达式的真假,如果为真,返回结果;如果为假,返回else值;如果未定义else值,则返回空值(使用条件确定返回值);
select name,id,(case when id=34 then salary*2
when id=45 then salary*3
else salary
end) new_salary
from semp;
-- -简单Case函数
简单Case表达式的作用是: 使用表达式确定返回值:
select id,name,(case sex
when '1' then '男'
when '2' then '女'
else '其他' end)
from student;
这两种方法可以实现相同的功能. 简单Case函数的写法比较简单,但是和case搜索函数相比,功能方面会有些限制,比如判断式。
还有一个需要注意的问题,Case函数只返回第一个符合条件的值,剩下的Case部分将会被自动忽略。
比如下面 SQL,将无法得到第二个结果:(差永远获取不到)。
sql如下
case when colum in ('a', 'b') then '优秀'
when colum in ('a') then '差'
else '其他' end
case when的常用应用场景:
等值转换
select name as '姓名',(case sex when 0 then '女' else '男' end) as '性别' from test.student;
范围转换
select name as '姓名',
(case when score > 90 then '优' when score >= 80 then '良' when score >= 60 then '及格' else '不及格' end) as '等级'
from test.stu_score;
列转行操作:
select class_id,
(case when grade = 'primary' then rate else 0 end) as 'primary',
(case when grade = 'middle' then rate else 0 end) as 'middle',
(case when grade = 'high' then rate else 0 end) as 'high'
from mst_class;
配合聚合做统计:
SELECT
sum(third_real_amount) txAmount,
count(bill_detail_id) txCount,
sum(case when bill_type = 2 then third_real_amount else 0 end) refundAmount ,
count(case when bill_type = 2 then bill_detail_id end) refundCount,
sum(case when bill_type = 1 then third_real_amount else 0 end) amount,
count(case when bill_type = 1 then bill_detail_id end) count,
sum(channel_fee) serviceCharge
from ${table}
WHERE
status=1
when中也可以使用and等组合多个条件
SELECT
column1,
column2,
CASE
WHEN condition1 AND condition2 THEN result1
WHEN condition3 AND condition4 THEN result2
ELSE default_result
END AS result_column
FROM
your_table;
格式化时间查询
时间转字符串:select date_format(now(), '%Y-%m-%d');
字符串转时间: select str_to_date('2020-11-02', '%Y-%m-%d %H:%i:%s');
字符串转时间戳:
select unix_timestamp(); #无参数,和传入now()都是获取当前时间时间戳
select unix_timestamp('2020-11-01'); #传入时间格式的字符串,转换为与时间参数对应的时间戳
时间戳转时间
select from_unixtime(1604483158); #转换成对应时间戳的时间格式
select from_unixtime(1604483158,’%Y-%m-%d’); #第一个参数是要转换的时间戳,第二个参数是时间格式类型的样式
拼接字符串
CONCAT(a.trade_no,'_jc')
查询练习
1、用两种方式根据部门号从高到低,工资从低到高列出每个员工的信息。
employee:
eid,ename,salary,deptid;
select * from employee order by deptid desc,salary asc;
select eid,ename,salary,deptid from employee order by deptid desc,salary asc;
2、列出各个部门中工资高于本部门的平均工资的员工数和部门号,并按部门号排序
select depatno, count(*) from depat as a,
(select depatno, avg(sal) as avgsal from depat group by depatno)as b,
where a.depatno=b.depatno
and a.sal>b.avgsal
group by a.depatno
order by a.depatno
用一条SQL语句 查询出每门课都大于80分的学生姓名
select distinct name from score where name not in (select distinct name from score where score<=80);
统计每年每月的信息
year month amount
1991 1 1.1
1991 2 1.2
1991 3 1.3
1991 4 1.4
1992 1 2.1
1992 2 2.2
1992 3 2.3
1992 4 2.4
查成这样一个结果
year m1 m2 m3 m4
1991 1.1 1.2 1.3 1.4
1992 2.1 2.2 2.3 2.4
select sales.year ,
(select t.amount from sales t where t.month='1' and t.year= sales.year) 'm1',
(select t.amount from sales t where t.month='1' and t.year= sales.year) 'm2',
(select t.amount from sales t where t.month='1' and t.year= sales.year) 'm3',
(select t.amount from sales t where t.month='1' and t.year= sales.year) as 'm4'
from sales group by year;
删除除了id号不同,其他都相同的学生冗余信息
2.学生表 如下:
id号 学号 姓名 课程编号 课程名称 分数
1 2005001 张三 0001 数学 69
2 2005002 李四 0001 数学 89
3 2005001 张三 0001 数学 69
A:
delete from tablename where id号 not in(select min(id号) from tablename group by 学号,姓名,课程编号,课程名称,分数)
求出小于45岁的各个老师所带的大于12岁的学生人数
数据库中有3个表 teacher 表,student表,tea_stu关系表。
teacher 表 teaID name age
student 表 stuID name age
teacher_student表 teaID stuID
要求用一条sql查询出这样的结果
1.显示的字段要有老师name, age 每个老师所带的学生人数
2 只列出老师age为40以下,学生age为12以上的记录
SELECT teacher.teaid,
teacher.name,
total
FROM teacher ,
(SELECT tea_stu.tea id,
count(*) total
FROM student,tea_stu
WHERE student.stuid=tea_stu.stuid
AND stu dent.age>12
GROUP BY tea_stu.teaid) AS tea_stu2
WHERE teacher.teaid=tea_stu2.tea id
AND teacher.age<45;
这样也行
SELECT tea. name,
tea.age,
count(u.id)
FROM teacher tea, tea_stu ts, student u
WHERE tea.age < 45
AND tea.id = ts.teaid
AND u.id = ts.stuid
AND u.age > 12
GROUP BY tea.id
求出发帖最多的人:
SELECT authorid,
count(*) total
FROM articles
GROUP BY authorid
HAVING total=
(SELECT max(total2)
FROM
(SELECT count(*) total2
FROM articles
GROUP BY authorid) AS t);
思路:要查询最多,就要先查询各用户发帖数量,然后找到最多的数量。
一个用户具有多个角色,请查询出该表中具有该用户的所有角色的其他用户。
SELECT count(*) AS num,
tb.id
FROM tb,
(SELECT role
FROM tb
WHERE id=xxx) AS t1
WHERE tb.role = t1.role
AND tb.id != t1.id
GROUP BY tb.id
HAVING num =SELECT count(role)
FROM tb
WHERE id=xxx;
思路:首先要知道该用户有哪些角色,select role from tb where id=xxx,然后是查询和该用户有相同角色的所有其他用户,where tb.role = t1.role and tb.id != t1.id,然后就是看角色的数量,相同的就是了。
查询与名称为殷天正的员工的工作,部门以及工资相同的员工信息
select * from emp where (job,deptno,sal) in (select job,deptno,sal from emp where ename=’殷天正’)
查询大于30部门所有员工工资的员工信息,包含30部门员工
select * from emp where sal>all(select sal from emp where deptno=30)
查询大于30部门其中任意一个员工工资的员工信息,包含30部门员工
select * from emp where sal>any(select sal from emp where deptno=30)
a,b,c三张表分别有id,score,name三个字段,表之间无关系根据score对所有字段排倒序
利用union all联合查询
查看代码
SELECT e.score,
e.name,
e.id from(
(SELECT score,
name,
id
FROM a
ORDER BY score)
UNION
all
(SELECT score,
name,
id
FROM b
ORDER BY score)union all
(SELECT score,
name,
id
FROM c
ORDER BY score)) e
ORDER BY e.score desc
查询在一个表中有另一个表中没有的数据
SELECT A.* FROM A LEFT JOIN B ON (A.id = B.id)
WHERE b.id IS NULL
select * from B
where (select count(1) as num from A where A.ID = B.ID) = 0

浙公网安备 33010602011771号