【06】MySQL-查询数据
注意:
1 当一个查询语句同时出现 where
,group by
, having
, order by
的时候,执行顺序和编写顺序是:
- 执行
where xx
对全表数据做筛选,返回第1个结果集; - 针对第1个结果集使用
group by
分组,返回第2个结果集; - 针对第2个结果集中的每一组数据执行
select xx
,有几组就执行几次,返回第3个结果集; - 针对第3个结果集使用
having xx
进行筛选,返回第4个结果集; - 针对第4个结果集排序。
- 即:
where --> group by -->select -->having -->order by
🔵🔵🔵
2 HAVING
和WHERE
都是用来过滤数据,区别在哪?
HAVING
在数据分组之后进行过滤选择分组,
而 WHERE
在分组之前用来选择记录。
WEHER`排除的记录不在分组内
基本格式:
SELECT
{* | <字段列表>}
[
FROM <表1>,<表2>....
[
WHERE <表达式>
[GROUP BY <group by dedinition>]
[HAVING <expression> [{<operator><expression>}...]]
[ORDER BY <order by definition>]
[LIMIT [<offset>,] <row count>]
]
]
SELECT [字段1,字段2,...字段n]
FROM [表或视图]
WHERE [查询条件];
where
条件查询
-- 查询不在20-30岁的员工
SELECT *
FROM emp
WEHER age NOT BETWEEN 20 AND 30;
-- like
-- 查询所有以‘b'开头的水果
SELECT *
FROM fruits
where f_name LIKE 'B%';
-- 查询名字包含'g'的水果
select *
from fruits
where f_name like '%g%'
-- 查询以字母y结尾,并且前面只有4个字符的记录
select *
from fruits
where f_name like '____y'
-- 查询结果不重复:distinct关键字
-- 格式:SELECT DISTINCT 字段名 FROM 表名
-- 查询所有有员工的部门编号
select distinct deptId from emp;
-- 对查询结果排序,order by
-- 指定排序方向 desc 降序排序
SELECT price
FROM products
ORDER BY DESC;
group by
分组
-- group by
-- 查询每个水果商提供的水果种类
select s_id, count(*) as Total
from fruits
group by s_id
-- 联合Having查询, ’并显示水果种类>1的分组信息
select s_id,GROUP_COUCAT(f_name) AS Names
from fruits
GROUP BY s_id
HAVING COUNT(f_name) > 1
-- 在group by 子句中使用with rollup
-- WITH ROLLUP :在所有查询出的分组记录之后增加一条记录,
-- 该记录查询出所有的记录的综合,即统计记录数量
-- 根据s_id , 对fruit表中的数据进行分组,并显示记录数目
select s_id, count(*) as Total
from fruits
group by s_id WITH ROLLUP
-- 还可以多字段进行分组
- 分组后的
Having
操作
-- 查询订单价格大于100的订单号和总订单价格
SELECT o_num, SUM(querytity * item_price) AS orderTotal
FROM orderitems
GROUP BY o_num
HAVING SUM(querytity * item_price) >= 100;
-- 联合Order By
-- 对总订单价格进行排序
SELECT o_num, SUM(querytity * item_price) AS orderTotal
FROM orderitems
GROUP BY o_num
HAVING SUM(querytity * item_price) >= 100
ORDER BY orderTotal;
…
【07】MySQL-增删改
- 插入数据
-- 创建表
CREATE TABLE person
(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(40) NOT NULL DEFAULT '',
age INT NOT NULL DEFAULT 0,
info CHAR(50) NULL,
PRIMARY KEY(id)
);
-- 插入
-- 1.单条插入(未指定列名
insert into person
values (1,'lishi',12,Lawyer);
-- 2.多条插入
insert into person
values (1,'lishi',12,Lawyer),
(null,'libai',32,Cleaner),
(null,'shushi',43,Student);
-- 注:这种一条insert语句插入多条数据
-- 比多条insert语句插入单条数据的效率高
-- 3.指定列名插入
insert into person(name,age,info)
values ('lishi',18,'Teacher');
-- 4.将查询结果插入到表内
CREATE TABLE person_new
(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(40) NOT NULL DEFAULT '',
age INT NOT NULL DEFAULT 0,
info CHAR(50) NULL,
PRIMARY KEY(id)
);
-- 将旧表内数据插入到新表内
INSERT INTO person_new (id,name,age,info)
SELECT id,name,age,info
FROM person;
- 更新数据
-- 格式:update tab_name set coL_name1 = value1,col_name2 = value2 ...
-- where (condition)
-- 如果不使用where会更新整列
update person set age = 18 ,name = 'yangxu'
where id = 1;
- 删除数据
-- 格式:delete from tab_name [where <condition>]
delete from person
where id = 2;
练习:
-- p175:
USE market;
CREATE TABLE fruits
(
f_id CHAR(10) NOT NULL,
s_id INT NOT NULL,
f_name CHAR(255) NOT NULL,
f_price DECIMAL(8,2) NOT NULL,
PRIMARY KEY(f_id)
);
-- 插入数据
INSERT INTO fruits VALUES
('a1',101,'apple',5.2),
('a2',102,'apple',5.2),
('a3',103,'apple',9.2),
('b1',101,'apple2',5.5),
('b2',106,'apple4',3.2),
('c1',102,'apple3',1.2),
('c2',103,'apple',7.2);
-- 查询
SELECT * FROM fruits;
-- 根据s_id对其分组
SELECT s_id,count(*) AS Total FROM fruits GROUP BY s_id;
-- 根据s_id,fruits表中的数据进行分组,将每个水果供应商的水果名称打印出来
SELECT s_id,GROUP_CONCAT(f_name) AS Names
FROM fruits
GROUP BY s_id;
-- LIMIT
SELECT * FROM fruits LIMIT 0,2;
-- 集合函数查询 ,查询所有水果数目
/*
注:count(*)和count(字段名)的区别?
count(*):计算表中总的行数,无论某列是否为null
count(字段名):计算时忽略null
*/
SELECT count(*) as TotalNum FROM fruits;
-- AVG():返回某列平均值
-- SUM():返回某列总和 ,忽略 NULL
-- Max(),Min() :返回某列最大最小值
SELECT SUM(f_price) AS TotalCount FROM fruits WHERE s_id = 101;
SELECT MAX(f_price) AS max_price FROM fruits ;
SELECT MIN(f_price) AS min_price FROM fruits;
-- MAX(),MIN() 还可以用于查找字符类型
SELECT MAX(f_name) FROM fruits;
-- 查找fruits表中不同供应商提供的水果价格最高的水果
-- 分析:1.先按供应商分组,2.使用max()求最大
SELECT f_name,s_id,MAX(f_price) as max_price
FROM fruits
GROUP BY s_id;
/*
* 当一个查询语句同时出现where,group by,having,order by的时候,执行顺序和编写顺序是:
1. 执行where xx对全表数据做筛选,返回第1个结果集;
2. 针对第1个结果集使用group by分组,返回第2个结果集;
3. 针对第2个结果集中的每一组数据执行select xx,有几组就执行几次,返回第3个结果集;
4. 针对第3个结果集使用having xx进行筛选,返回第4个结果集;
5. 针对第4个结果集排序。
*/
-- 内连接 1.使用where
SELECT supperliers.s_id,s_name,f_name,f_price
FROM fruits
WHERE supperliers.s_id = fruits.s_id;
-- 内连接 2.使用‘ 表1 INNER JOIN 表2 ON 表1.id = 表2.id
SELECT supperlisers.s_id ,s_name,f_name,f_price
FROM fruits
INNER JOIN supperliers
ON fruits.s_id = supperliers.s_id;
-- 自连接 查询供应f_id = 'a1'的水果供应商提供的其他水果种类
SELECT f1.f_id,f1.f_name
FROM fruits AS f1,fruits AS f2
WHERE f1.s_id = f2.s_id
AND f2.f_id = 'a1';
-- 外连接
-- LEFT JOIN
-- RIGHT JOIN
-- 创建演示表
CREATE TABLE `orders` (
`o_num` int(4) NOT NULL,
`o_date` datetime NOT NULL,
`c_id` int(4) NOT NULL,
PRIMARY KEY (`o_num`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- LEFT JOIN :返回左表中的所有记录 和 右表中连接字符相等的记录
-- 查询所有客户,包括没有订单的客户(即:customers 中order_id为 NULL的客户
SELECT customers.c_id,orders.o_num
FROM customers LEFT JOIN orders
ON customers.c_id = orders.c_id;
-- RIGHT JOIN :同上,右表所有记录+连接字符相等记录
-- LIKE
SELECT * FROM fruits WHERE f_name LIKE '%app%';
-- 使用正则表达式
-- ^ , $ , . , * , + , <字符串> , [字符集合] , [^] , 字符串{n,} ,字符串{n,m}
-- 用法:
SELECT * FROM fruits WHERE f_name REGEXP '^a';
SELECT * FROM fruits WHERE f_name REGEXP 'a$';
-- *:匹配前面的字符任意多次 以b开头,且b后面出现字母a
SELECT * FROM fruits WHERE f_name REGEXP '^ba*';
-- 其他都是类似的
-- EXISTS关键字的子查询
-- 查询suppliers表中是否存在s_id=107的供应商,如果存在,则查询fruits表中的记录
SELECT *
FROM fruits
WHERE EXISTS
(SELECT s_name FROM suppliers WHERE s_id = 107);
-- 查询suppliers表中是否存在s_id=107的供应商,如果存在,则查询fruits表中f_price>10.20的记录
SELECT *
FROM fruits
WHERE f_price > 10.20 AND EXISTS
(SELECT s_name FROM suppliers WHERE s_id = 107);
-- 带IN关键字的子查询,
-- 在orderitems表中查询f_id为c0的订单号,并根据订单号查询具有订单号的客户c_id
SELECT c_id
FROM orders
WHERE o_num IN
(SELECT o_num FROM orderitems WHERE f_id = 'c0');
-- p230练习:
-- 1.建表
CREATE TABLE dept
(
d_no INT NOT NULL PRIMARY KEY auto_increment, -- 部门编号
d_name VARCHAR(50) NOT NULL, -- 部门名称
d_location VARCHAR(50) -- 部门地址
);
CREATE TABLE emp
(
e_no INT(11) NOT NULL PRIMARY KEY,
e_name VARCHAR(50) NOT NULL,
e_gender CHAR(2),
dept_no INT(11) NOT NULL, -- 外键,部门编号
e_job VARCHAR(50) NOT NULL,
e_salary INT(11) NOT NULL,
hireDate DATE NOT NULL,
CONSTRAINT dno_fk FOREIGN KEY(dept_no) REFERENCES dept(d_no)
);
-- 插入数据
INSERT INTO dept
VALUES (10,'Accounting','Shanghai'),
(20,'Research','Beijing'),
(30,'Sales','Shenzhen'),
(40,'Operations','Fujian');
INSERT into emp
VALUES
(1001,'小白1','m',20,'前台',800,'2005-11-20'),
(1002,'小白2','w',30,'后台',800,'2001-11-20'),
(1003,'小白3','w',20,'老板',1800,'2000-11-20'),
(1004,'小白4','m',10,'前台',1200,'2001-11-20'),
(1005,'小白5','w',20,'后台',2800,'1998-11-20'),
(1006,'小白6','m',40,'后台',4800,'2005-11-20'),
(1007,'小白7','m',20,'审计',1800,'1995-11-20'),
(1008,'小白8','w',30,'前台',700,'2015-11-20'),
(1009,'小白9','m',40,'审计',300,'2005-11-20'),
(1010,'小白10','w',20,'前台',900,'2010-11-20'),
(1011,'小白11','w',20,'经理',3800,'1990-11-20'),
(1012,'小白12','m',30,'前台',800,'2005-11-20');
-- 1.在emp表查询所有记录的e_no,e_name,e_salary
SELECT e_no,e_name,e_salary
FROM emp;
-- 2.在emp表,查询dept_no=10和20的所有记录
SELECT *
FROM emp
WHERE dept_no in(10,20);
-- 3.emp,查询工资在800-2500
SELECT *
FROM emp
WHERE e_salary BETWEEN 800 and 2500;
-- 4,emp表 查询部门编号为20的部门的员工信息
SELECT *
FROM emp
WHERE dept_no = 20;
-- 5.查询每个部门最高工资的员工信息
SELECT e_name,dept_no,MAX(e_salary)
FROM emp
GROUP BY dept_no;
-- 6.查询小白6所在部门和部门所在地
SELECT d_name,d_location
FROM emp,dept
WHERE emp.dept_no = dept.d_no AND emp.e_name = '小白6';
-- 7.使用连接查询,查询所有员工的部门和部门信息
SELECT *
FROM emp,dept
WHERE emp.dept_no = dept.d_no;
-- 8.emp表,计算每个部门有多少员工
SELECT dept_no,count(*) AS total
FROM emp
GROUP BY dept_no;
-- 9.emp表,计算不同类型职工的总工资数
SELECT dept_no,sum(e_salary)
FROM emp
GROUP BY dept_no;
-- 10.emp表,计算不同部门的平均工资
SELECT dept_no,AVG(e_salary)
FROM emp
GROUP BY dept_no;
-- 11.emp表,查询工资低于1500的员工
SELECT *
FROM emp
WHERE e_salary <1500;
-- 12.emp表,将查询记录先按部门降序排列,再按员工工资降序排序
SELECT e_name,dept_no,e_salary
FROM emp
ORDER BY dept_no,e_salary DESC;
-- 13.emp表,查询员工姓名以‘白’结尾的员工信息
SELECT *
FROM emp
WHERE e_name REGEXP '白$';
-- 14.emp表,查询到目前为止,工龄大于10年的员工信息
SELECT *
FROM emp
WHERE (YEAR(CURDATE())-YEAR(hireDate)) > 10;
-- 15.emp表,计算所有女员工的工龄
SELECT e_name,(YEAR(CURDATE())-YEAR(hireDate)) as gonli
FROM emp
WHERE e_gender = 'w';
-- 16.emp表,查询从第3条记录开始到第7条
SELECT *
FROM emp
LIMIT 2,5;