1.查看当前所有数据库
show databases;
2.打开指定的库
use 库名
3.查看当前库的所有表
show tables;
4.查看其他库的所有表
show tables from 库名;
5.创建表
create table 表名(
列名 列类型,
列名 列类型,
...
);
6.查看表结构
desc 表名;
7.查看服务器版本
方式一:登录到mysql服务端
select version();
方式二:没有登录到mysql服务端
mysql --version
1、基础查询
8.起别名(as可省略)
select sname as 姓名 from student;
select sname 姓名 from student;
9.查询字段
select sname as 姓名,classNum as 班级编号 from srudent;
10.查询所有字段
select * from student
11.查询常量
select 100 as 常量
12.查询表达式
select 100%98 as 表达式结果
13.查询函数
select version() as 函数结果
14.拼接字段
+号的作用:
select 100 + 90; #结果为190,在SQL中+为运算符,在java中,+号既可以做运算符,又可以做连接符
select '100' + 90; #结果为190,试图将字符型转化为数值型
select 'like' + 90; #结果为90,字符型转换不成数值型,便是0
select null + 90; #结果为0,只要一方为null,结果为null
concat函数的作用:拼接字符串
select concat(sname,ssex) as 姓名性别 from student
15.去重
select distinct classNum as 班级编号 from student
16.ifnull(args1,args2)函数
select ifnull(sbirthday,0) from student #查看学生表里的生日,如果生日为null,那么将用0代替null
2、条件查询
简单条件运算符:>、<、=、!=、<>、>=、<=
逻辑运算符:&&、||、!、and、or、not
模糊查询:like、between...and...、in、is null
简单查询:
select sname as 姓名 from student where classNum <> 102; #查询班级编号不等于102的学生姓名
select * from student where sno >= 03 and sno <= 07; #查询学生编号在03-07之间的学生信息
select * from student where sno < 03 or sno > 07 or classNum = 102;#查询学生编号不是在03-07之间的信息或者班级为102的学生信息
逻辑查询
还可以这样写:
select * from student where not(sno>=03 and sno <=07) or classNum = 102;
模糊查询:%表示通配符,可以表示任意多个字符,包括0个,_
也表示通配符,不过下划线只能表示一个字符
select * from student where sname like '娃%'; #查询头部为娃的同学信息
select * from student where sname like '%娃'; #查询尾部为娃的同学信息
select * from student where sname like '%娃%'; #查询包含娃字符的同学信息
select * from student where sname like '_娃%'; #查询第二个字符为娃的同学信息
如果模糊查询条件里有的条件,比如查询第二个字符为的数据,那就要对第二个_进行转义
select * from student where sname like '_\_%';
select * from student where sname like '_$_%' escape '$'; #自定义转义字符
select * from student where sno between 03 and 05; #包含临界值,不要调换两个临界值的顺序,完全等价于>=03 <=05
select * from student where sno in(03,04,05); #in后面加的是个集合,in列表的值必须兼容或者一致
=和我<>符号不能判断null值,要用is null和is not null
select * from student where sbirthday is null; #只能判断null,不能判断其他数据类型
安全等于<=>,既可以判断Null又可以判断正常数据类型
select * from student where sbirthday <=> null;
select * from student where sname <=> '大娃';
3、 排序查询
select * from student order by sbirthday desc; #降序排列
select * from student order by sbirthday asc; #升序排列
select * from student order by sbirthday; #默认是升序
SELECT CONCAT(last_name,first_name) AS 姓名,department_id AS 部门号,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM employees
ORDER BY 年薪 DESC ,ORDER BY 姓名 ASC;
SELECT CONCAT(last_name,first_name) AS 姓名,salary
FROM employees
WHERE salary < 8000 OR salary > 17000 ORDER BY salary DESC;
SELECT * FROM employees
WHERE email LIKE '%e%' ORDER BY LENGTH(email) DESC ,ORDER BY partment_id ASC;
4、函数
单行函数:concat、length、ifnull等
分组函数:做统计使用,又称为统计函数、聚合函数、组函数
4.1、常见函数
length():查看里面的str的字节个数,utf8下一个英文占一个字节,一个中文占3个字节
select length('John');
select length('哈哈哈hahaha');
concat():拼接字符串
select concat(sname,classNum) as 姓名班级 from student;
upper():转大写 lower():转小写
select upper('John');
select lower('John');
substr():截取字符串
SQL中,索引从1开始,不像java索引从0开始
select substr('杨过和小龙女',4); #小龙女
select substr('杨过和小龙女',3,4); #和小龙女,3表示从哪里开始,4表示截取的个数,不是结束索引
instr():查询子字符串第一次出现的时候的索引
select instr('杨过和小龙女和杨过','杨过');
trim():去掉多余的空字符
select trim(' 杨过 ');
select trim('a' from 'aaaaaa杨aaaaa过aaaaaaaaa');#去掉有效字符的前后的a字符,杨过中间的a为有效字符
lpad():左填充 rpad右填充
select lpad('白素贞',10,'*'); #*******白素贞,字符不够的左边填充*
replace():替换字符串
select replace('张无忌爱上了周芷若','周芷若','赵敏');
数学函数
round():四舍五入
select round(-1.55);
select round(-1.567,2); #保留两位
ceil():向上取整
select ceil(1.00); #1
select ceil(1.02); #2
select ceil(-1.02); #-1
floor():向下取整
select floor(1.00); #1
select floor(1.02); #1
select floor(-1.02); #-2
truncate():截断
select truncate(1.566666,1); #从小数点后一位进行截断,1.5
mod():取模就是去余数 mod(a,b) : a-a/b*b;被除数为正,结果为正,被除数为负,结果为负
select mod(10,3); #1
select 10%3; #1
日期函数
select now(); #返回系统当前日期+时间
select curdate(); #返回系统当前日期
select curtime(); #返回系统当前时间
select year(now()); #当前年份
select datediff('2020-04-06','2020-04-07'); #查看两个日期的相差天数
其他函数
select version(); #查看当前版本
select database(); #查看当前数据库
select user(); #查看当前用户
流程控制函数
if(表达式,true取值,false取值)
select if(10>5,'大','小');
case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end
案例:查询员工的工资,要求
部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
部门号=50,显示的工资为1.3倍
其他部门,显示的工资为原工资
select salary as 原始工资,department_id,
case department_id
when 30 then salary*1.1
when 40 then salary*1.2
when 50 then salary*1.3
else salary
end as 新工资
from employees
case
when 表达式1 then 要显示的值1或者语句1;
when 表达式2 then 要显示的值2或者语句2;
...
else 要显示的值n或者语句n
end as 等级
from employees
select salary,
case
when salary>20000 then 'A'
when salary>15000 then 'B'
when salary>10000 then 'C'
else 'D'
end as 等级
from employees
SELECT NAME,price,
CASE
WHEN price>5000 THEN '贵'
WHEN price>3000 THEN '一般'
WHEN price>1000 THEN '便宜'
ELSE '小于1000'
END AS 等级
FROM route ORDER BY price desc
4.2、分组函数
特点:
1、sum、avg一般处理数值型
max、min、count可以处理任意类型
2、0+Null都等于Null,以上分组函数都忽略null值
3、可以和distinct配合使用
4、和分组行数一同查询的字段有限制,因为分组行数查询出来的是一行数据,字段却有很多行数据,最终只会显示一行,和分组函数一同查询的字段要求是group by 后的字段,group by的意思是分组,可以将下过单的用户分组,分别查询每个用户下单的平均值,不然为啥叫分组行数呢,哈哈哈
sum():计算和
select sum(totalPrice) from orders
avg():计算平均值
select avg(totalPrice) from orders
max():计算最大值
select max(totalPrice) from orders
min():计算最小值
select min(totalPrice) from orders
count():计算该字段的非空个数
select count(totalPrice) from orders
可以合并:
SELECT SUM(totalPrice) 总价,ROUND(AVG(totalPrice)) 平均值,MAX(totalPrice) 最大值,MIN(totalPrice) 最小值,COUNT(totalPrice) 总个数 FROM orders
也可以查时间的最早和最晚
SELECT MAX(orderTime) 最晚下单时间,MIN(orderTime) 最早下单时间 FROM orders;
SELECT SUM(DISTINCT totalPrice) 去重后,SUM(totalPrice) 去重前 FROM orders;
查看有多少人下过单:去重、求和
SELECT COUNT(DISTINCT userId) FROM orders;
查看每个用户下单的钱的总和
SELECT SUM(totalPrice),userId FROM orders GROUP BY userId
查看最晚下单和最早下单相隔的天数
SELECT DATEDIFF(MAX(orderTime),MIN(orderTime)) FROM orders;
查看自己活了多少天
SELECT DATEDIFF(NOW(),'1998-07-24') AS 活了多少天
补充:
select count(*) from orders;
select count(1) from orders;
都表示查询所有行数的个数、
MYISAM存储引擎下,count()的效率高,因为该引擎下有计数器,可以直接返回行数
INNODB存储引擎下,count()和count(1)的效率差不多,比count(字段)要高一些
5、分组查询
基础格式
select 分组函数,分组字段 from 表名 [where 查询条件] group by 分组字段
简单分组查询:将一列字段进行分组,同样的放在一块
SELECT userId FROM orders GROUP BY userId
一般将分组函数和分组查询一块使用
比如查询每人的平均消费值
SELECT AVG(totalPrice) AS 平均消费,userId FROM orders GROUP BY userId
复杂一点的分组查询:
查询下单超过两单的用户
分析:第一、先按照用户分组,第二再去判断下单数是不是大于2
where后面指定查询条件指的是原表的,这里是在一个分组查询后的新表做判断,所用条件用having来连接,放在分组后
第一步
SELECT COUNT(*),userId FROM orders GROUP BY userId;
第二步
SELECT COUNT(*),userId FROM orders GROUP BY userId HAVING COUNT(*) > 2;
涉及到分组查询的条件时,如果条件在原表中有可以用where(在group by前面),如果在分组后的结果集中就用having(在group by后面)连接查询条件。
按每个字段分组
按用户id和旅游路线id进行分组,并查询每一组的平均值
SELECT AVG(totalPrice),userId,routeId FROM orders GROUP BY userId,routeId
添加排序
SELECT AVG(totalPrice),userId,routeId FROM orders GROUP BY userId,routeId ORDER BY AVG(totalPrice) desc
6、表连接
按功能分类
内连接:等值连接、非等值连接、自连接
外连接:左外连接、右外连接、全外连接
交叉连接
6.1、Sql92语法
6.1.1等值连接
查看订单编号(在订单表中)和下单账号名(在用户表中),并按用户名排序
SELECT orderNum,username FROM orders,USER WHERE orders.userId = user.id ORDER BY username;
查看订单编号和下单产品
有时候表名比较长,又多处会用到,就可以为表名取别名,跟为字段取别名一样,用as或者空格,同样可以区分不同表的同名字段,不过如果为表起了别名,就不能再使用原表名.字段名
SELECT o.orderNum,r.name FROM orders o,route r WHERE o.routeId = r.id;
实现三表连接
SELECT o.orderNum,u.username,r.name FROM orders o,USER u,route r WHERE o.userId = u.id AND o.routeId = r.id ORDER BY username;
6.1.2非等值连接
就是where后面的查询条件不再是等值判断,变成了区间判断比如:> < >= <= <> between and等等
查询订单表里下单的用户名以及价格大于10000的订单价格
SELECT username,totalPrice FROM USER u,orders o WHERE u.id = o.userId AND o.totalPrice > 10000;
6.1.3自连接:自己表连接自己表
把自己表当成多份表来使用
sql92语法练习
SELECT job_id,location_id FROM employees e,department d WHERE e.department_id = d.department_id AND e.department_id = 90;
SELECT e.last_name,d.department_name,d.location_id,l.city FROM employees e,department d,locations l
WHERE e.department_id = d.department_id AND d.location_id = l.location_id AND e.commosion_pct IS NOT NULL;
SELECT e.last_name,e.job_id,e.department_id,d.department_name FROM employees e,department d,locations l
WHERE e.department_id = d.department_id AND d.location_id = l.location_id AND l.city = 'Toronto';
SELECT department_name,job_title,MIN(salary) FROM employees e,jobs j,department d
WHERE e.department_id = d.department_id AND e.job_id = j.job_id GROUP BY department_name,job_title;
SELECT COUNT(*),country_id FROM department d,locations l
WHERE d.location_id = l.location_id GROUP BY country_id HAVING COUNT(*) > 2;
SELECT e.last_name AS employees,e.employee_id AS "Emp#",m.last_name AS manager,m.employee_id AS "Mgr#"
FROM employees e,employees m WHERE e.manager_id = m.employee_id;
6.2、Sql99语法
select 查询列表
from 表1 别名 【连接条件】
join 表2 别名
on 【表连接条件】
【where 筛选条件】
【group by 分组】
【having 筛选条件】
【order by 排序条件】
【limit 选取个数】
表连接条件
内连接:inner
外连接:左外连接(left 【outer】)、右外连接(right【outer】)、全外连接(full 【outer】)
交叉连接:cross
6.2.1内连接(inner可以省略 )
select 查询列表
from 表1 别名 inner
join 表2 别名
on 【表连接条件】
【where 筛选条件】
【group by 分组】
【having 筛选条件】
【order by 排序条件】
【limit 选取个数】
SELECT last_name,department_name
FROM employees e INNER JOIN department d ON e.department_id = d.department_id
SELECT last_name,job_title
FROM employees e INNER JOIN jobs j ON e.job_id = j.job_id
WHERE last_name LIKE '%e%';
SELECT COUNT(*),city
FROM department d INNER JOIN locations l ON d.location.id = l.location_id
GROUP BY city HAVING COUNT(*) > 3
SELECT department_name,COUNT(*) AS 员工个数
FROM department d INNER JOIN employees e ON e.department_id = d.department_id
GROUP BY department_name HAVING COUNT(*) > 3
ORDER BY 员工个数 DESC;
SELECT e.last_name,d.department_name,j.job_title
FROM employees e
INNER JOIN department d ON e.department_id = d.department_id
INNER JOIN jobs j ON e.job_id = j.job_id
ORDER BY department_name DESC;
6.2.3外连接
特点:
1.外连接的查询结果是主表中的所有记录
2.如果从表中有和它匹配的,则显示匹配的值,如果从表中没有和它匹配的,则显示为null
3.外连接查询结果=内连接结果+主表中有而从表中没有的记录
4.左外连接:left outer join:left左边的是主表;right outer join :right join 右边的是主表
左外连接左边的是主表,右外连接右边的是主表
内连接查的是两个表都有的数据
外连接可以查出一个表有另一个表没有的数据,没有的就用Null来填充
左外连接
SELECT s.name,s.destId,d.name
FROM scenery s
LEFT OUTER JOIN destination d ON s.destId = d.id;
SELECT d.id,d.name,COUNT(*) AS 景点个数
FROM destination d
LEFT OUTER JOIN scenery s ON d.id = s.destId
WHERE s.name IS NOT NULL
GROUP BY d.name;
右外连接
SELECT s.name,s.destId,d.name
FROM scenery s
RIGHT OUTER JOIN destination d ON s.destId = d.id;
6.2.4交叉连接
查的就是笛卡尔积
SELECT u.*,r.*
FROM USER u
CROSS JOIN role r;
练习
SELECT g.name,g.boyId,b.*
FROM girl g
LEFT OUTER JOIN boy b ON g.boyId = b.id
WHERE g.id > 3;
SELECT city,d.*
FROM locations l
LEFT OUTER department d ON d.location_id = l.locationId
WHERE d.department_id IS NULL;
SELECT e.*,department_name
FROM employees e
LEFT OUT JOIN department d ON e.department_id =d.department_id
WHERE d.department_name = 'SAL' OR d.department_name = 'IT';