MySQL(7):CRUD语句(3)——子查询和多表查询、蠕虫复制
2016-12-29 23:38
399 查看
# 多表查询
# 交叉连接
SELECT COUNT(*) FROM dept; -- m
SELECT COUNT(*) FROM emp; -- n
SELECT COUNT(*) FROM dept, emp; -- m * n
-- 标准写法
SELECT * FROM dept CROSS JOIN emp;
#内连接
-- 简化写法
SELECT * FROM dept d, emp e WHERE d.dId = e.dId;
-- 标准写法 (等值连接)
SELECT * FROM dept d INNER JOIN emp e ON d.dId = e.dId;
# 外连接
-- 左外连接
SELECT * FROM dept d LEFT JOIN emp e ON d.dId = e.dId;
-- 只限制一个表的行,不限制另一个表!
-- 左边的表作为主表,左边的表的记录会全部显示。
-- 如果主表还有数据,但on后面的条件不满足,会自动补上null
# 自连接
SELECT tb1.name, tb1.name FROM tb tb1, tb tb2 WHERE tb1.pId = tb2.id;
DROP TABLE IF EXISTS c;
CREATE TABLE c (
cId INT,
cName VARCHAR(32),
pId INT
);
INSERT INTO c (cId, cName,pId) VALUES (1,'java',NULL);
INSERT INTO c (cId, cName,pId) VALUES (2,'javaSE',1);
INSERT INTO c (cId, cName,pId) VALUES (3,'javaEE',1);
INSERT INTO c (cId, cName,pId) VALUES (4,'openSource',NULL);
INSERT INTO c (cId, cName,pId) VALUES (5,'openCL',4);
INSERT INTO c (cId, cName,pId) VALUES (6,'openCv',4);
INSERT INTO c (cId, cName,pId) VALUES (7,'android',4);
SELECT * FROM c;
SELECT c1.cName 类别, c2.cName 课程 FROM c c1, c c2 WHERE c1.cId = c2.pId;
-- 此时一定要给表取别名!
补充例题
第二天的温度比前一天的低的记录id有哪些?
select a.id from weather a , weather b where datediff(a.date, b.date) = 1 and a.temperature < b.temperature;
第二天的开盘价小于第一天收盘价的记录id有哪些?
select prevStock.id from stock a , stock b where datediff(a.date, b.date) = 1 and a.shoupan > b.kaipan;
SQL 子查询
摘自百度百科。
当一个查询是另一个查询的条件时,称之为子查询。
子查询可以使用几个简单命令构造功能强大的复合命令。
子查询最常用于SELECT-SQL命令的WHERE子句中。
子查询是一个 SELECT 语句,它嵌套在一个 SELECT、SELECT...INTO 语句、INSERT...INTO 语句、DELETE 语句、或 UPDATE 语句或嵌套在另一子查询中。
e.g.
CREATE TABLE clerk
(
cleId INT PRIMARY KEY,-- 主键
cleName NVARCHAR(50),
age INT
);
-- 查出年龄最大的人
select * from clerk where age = (select max(age) from clerk);
-- 查出年龄小于平均年龄的人
select * from clerk where age < (select avg(age) from clerk);
聚合函数再练习
-- 建立员工表
CREATE TABLE emp (
eId INT PRIMARY KEY AUTO_INCREMENT,
eName VARCHAR(64),
eJob VARCHAR(64),
sal INT,
hiredate DATE,
deptId INT
);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy1','销售',1000,NOW(),1);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy2','销售',1000,NOW(),1);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy3','销售',1200,NOW(),2);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy4','研发',1500,NOW(),1);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy5','研发',1600,NOW(),1);
-- 查询所有员工的平均工资
select avg(sal) 平均工资 from emp;
-- 查询高于平均工资的所有员工
select eName 姓名, sal 工资 from emp where sal > (select avg(sal) from emp);
-- 查询出不同岗位的平均工资
select eJob 岗位, avg(sal) 平均工资 from emp group by eJob; -- avg是在group by以后再对行求平均的
-- 查询研发岗位的平均工资
SELECT AVG(sal) FROM emp WHERE eJob = '研发'; -- 直接带where条件
select avg(sal) from emp group by eJob having eJob = '研发'; -- 用having写
-- 查询工资大于等于其所在部门平均工资的所有员工
SELECT emp.ename , emp.sal , tmp.myavg , emp.deptId FROM emp , (SELECT AVG(sal) myavg , deptId FROM emp
GROUP BY deptId) tmp WHERE emp.deptId = tmp.deptId AND emp.sal >= tmp.myavg;
-- 好诡异的写法!!!
1. 先查出各部门平均工资和部门Id,把结果作为临时表temp;
SELECT AVG(sal) myavg,deptId FROM emp GROUP BY deptId
2. 联合查询emp和temp表,条件是emp的部门Id = 临时表的部门Id
SELECT emp.ename,emp.sal,tmp.myavg,emp.deptId FROM emp,(SELECT AVG(sal) myavg,deptId FROM emp
GROUP BY deptId) tmp WHERE emp.deptId = tmp.deptId;
相当于是把每一个员工所在的部门的平均工资都列在员工表里面。故意造成数据冗余的结果,有助于查询。
而关系型数据库设计的时候,反而要消除这种冗余。
3. 再在where条件中添加 emp.sal >= tmp.myavg的条件,用AND连接。
-- 查出平均工资最高的岗位和对应的平均工资
直接查询出平均工资,降序排列,取第1条! -- 要学聪明一点!
select eJob, avg(sal) from emp group by eJob order by avg(sal) limit 0,1;
-- any 是什么意思?
-- all 是什么意思?
补充
把查出来的表又insert进某一张表
CREATE TABLE test1
(
testId INT PRIMARY KEY AUTO_INCREMENT, -- 自增长 从1开始,每次加1
testName VARCHAR(30),
testPass VARCHAR(30)
);
MySQL的蠕虫复制
INSERT INTO test1 (testName,testPass) VALUES ('qcy','qcy');
insert into test1 (testName, testPass) (select testName, testPass from test1); -- 这里没有values
SQLite的蠕虫复制
Insert Into sn_info(author,tutor,years,degree,speciality) select author,tutor,years,degree,speciality from xxx ;
SQL注入漏洞
SELECT * FROM cat;
-- 注入漏洞
SELECT * FROM cat WHERE catId = 1 AND catName = 'bb' OR 1 = '1'; -- 加上 or 1 = '1' (1 = 1 好像也可以……)
会返回表中的所有数据
第二天的开盘价小于第一天收盘价的记录id有哪些?
select prevStock.id from stock a , stock b where datediff(a.date, b.date) = 1 and a.shoupan > b.kaipan;
# 交叉连接
SELECT COUNT(*) FROM dept; -- m
SELECT COUNT(*) FROM emp; -- n
SELECT COUNT(*) FROM dept, emp; -- m * n
-- 标准写法
SELECT * FROM dept CROSS JOIN emp;
#内连接
-- 简化写法
SELECT * FROM dept d, emp e WHERE d.dId = e.dId;
-- 标准写法 (等值连接)
SELECT * FROM dept d INNER JOIN emp e ON d.dId = e.dId;
# 外连接
-- 左外连接
SELECT * FROM dept d LEFT JOIN emp e ON d.dId = e.dId;
-- 只限制一个表的行,不限制另一个表!
-- 左边的表作为主表,左边的表的记录会全部显示。
-- 如果主表还有数据,但on后面的条件不满足,会自动补上null
# 自连接
SELECT tb1.name, tb1.name FROM tb tb1, tb tb2 WHERE tb1.pId = tb2.id;
DROP TABLE IF EXISTS c;
CREATE TABLE c (
cId INT,
cName VARCHAR(32),
pId INT
);
INSERT INTO c (cId, cName,pId) VALUES (1,'java',NULL);
INSERT INTO c (cId, cName,pId) VALUES (2,'javaSE',1);
INSERT INTO c (cId, cName,pId) VALUES (3,'javaEE',1);
INSERT INTO c (cId, cName,pId) VALUES (4,'openSource',NULL);
INSERT INTO c (cId, cName,pId) VALUES (5,'openCL',4);
INSERT INTO c (cId, cName,pId) VALUES (6,'openCv',4);
INSERT INTO c (cId, cName,pId) VALUES (7,'android',4);
SELECT * FROM c;
SELECT c1.cName 类别, c2.cName 课程 FROM c c1, c c2 WHERE c1.cId = c2.pId;
-- 此时一定要给表取别名!
补充例题
第二天的温度比前一天的低的记录id有哪些?
select a.id from weather a , weather b where datediff(a.date, b.date) = 1 and a.temperature < b.temperature;
第二天的开盘价小于第一天收盘价的记录id有哪些?
select prevStock.id from stock a , stock b where datediff(a.date, b.date) = 1 and a.shoupan > b.kaipan;
SQL 子查询
摘自百度百科。
当一个查询是另一个查询的条件时,称之为子查询。
子查询可以使用几个简单命令构造功能强大的复合命令。
子查询最常用于SELECT-SQL命令的WHERE子句中。
子查询是一个 SELECT 语句,它嵌套在一个 SELECT、SELECT...INTO 语句、INSERT...INTO 语句、DELETE 语句、或 UPDATE 语句或嵌套在另一子查询中。
e.g.
CREATE TABLE clerk
(
cleId INT PRIMARY KEY,-- 主键
cleName NVARCHAR(50),
age INT
);
-- 查出年龄最大的人
select * from clerk where age = (select max(age) from clerk);
-- 查出年龄小于平均年龄的人
select * from clerk where age < (select avg(age) from clerk);
聚合函数再练习
-- 建立员工表
CREATE TABLE emp (
eId INT PRIMARY KEY AUTO_INCREMENT,
eName VARCHAR(64),
eJob VARCHAR(64),
sal INT,
hiredate DATE,
deptId INT
);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy1','销售',1000,NOW(),1);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy2','销售',1000,NOW(),1);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy3','销售',1200,NOW(),2);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy4','研发',1500,NOW(),1);
INSERT INTO emp (eName,eJob,sal,hiredate,deptId) VALUES ('qcy5','研发',1600,NOW(),1);
-- 查询所有员工的平均工资
select avg(sal) 平均工资 from emp;
-- 查询高于平均工资的所有员工
select eName 姓名, sal 工资 from emp where sal > (select avg(sal) from emp);
-- 查询出不同岗位的平均工资
select eJob 岗位, avg(sal) 平均工资 from emp group by eJob; -- avg是在group by以后再对行求平均的
-- 查询研发岗位的平均工资
SELECT AVG(sal) FROM emp WHERE eJob = '研发'; -- 直接带where条件
select avg(sal) from emp group by eJob having eJob = '研发'; -- 用having写
-- 查询工资大于等于其所在部门平均工资的所有员工
SELECT emp.ename , emp.sal , tmp.myavg , emp.deptId FROM emp , (SELECT AVG(sal) myavg , deptId FROM emp
GROUP BY deptId) tmp WHERE emp.deptId = tmp.deptId AND emp.sal >= tmp.myavg;
-- 好诡异的写法!!!
1. 先查出各部门平均工资和部门Id,把结果作为临时表temp;
SELECT AVG(sal) myavg,deptId FROM emp GROUP BY deptId
2. 联合查询emp和temp表,条件是emp的部门Id = 临时表的部门Id
SELECT emp.ename,emp.sal,tmp.myavg,emp.deptId FROM emp,(SELECT AVG(sal) myavg,deptId FROM emp
GROUP BY deptId) tmp WHERE emp.deptId = tmp.deptId;
相当于是把每一个员工所在的部门的平均工资都列在员工表里面。故意造成数据冗余的结果,有助于查询。
而关系型数据库设计的时候,反而要消除这种冗余。
3. 再在where条件中添加 emp.sal >= tmp.myavg的条件,用AND连接。
-- 查出平均工资最高的岗位和对应的平均工资
直接查询出平均工资,降序排列,取第1条! -- 要学聪明一点!
select eJob, avg(sal) from emp group by eJob order by avg(sal) limit 0,1;
-- any 是什么意思?
-- all 是什么意思?
补充
把查出来的表又insert进某一张表
CREATE TABLE test1
(
testId INT PRIMARY KEY AUTO_INCREMENT, -- 自增长 从1开始,每次加1
testName VARCHAR(30),
testPass VARCHAR(30)
);
MySQL的蠕虫复制
INSERT INTO test1 (testName,testPass) VALUES ('qcy','qcy');
insert into test1 (testName, testPass) (select testName, testPass from test1); -- 这里没有values
SQLite的蠕虫复制
Insert Into sn_info(author,tutor,years,degree,speciality) select author,tutor,years,degree,speciality from xxx ;
SQL注入漏洞
SELECT * FROM cat;
-- 注入漏洞
SELECT * FROM cat WHERE catId = 1 AND catName = 'bb' OR 1 = '1'; -- 加上 or 1 = '1' (1 = 1 好像也可以……)
会返回表中的所有数据
第二天的开盘价小于第一天收盘价的记录id有哪些?
select prevStock.id from stock a , stock b where datediff(a.date, b.date) = 1 and a.shoupan > b.kaipan;
相关文章推荐
- MySQL(4):CRUD语句(2)——基本查询
- 一条mysql查询语句
- mysql的经典查询语句
- 设计高效合理的MySQL查询语句讲解
- JAVA连接MYSQL,查询 ,添加,删除,语句
- 如何设计高效合理的MySQL查询语句
- 从一个MySQL的例子来学习查询语句
- mysql limit查询语句优化原则
- 收集的mysql热复制的资料与常用语句
- mysql语句查询-从表中选择想查看的位置和条数
- mysql的经典查询语句
- J2EE入门视频教程第五讲——MySQL中的数据类型及命令行基本查询语句
- 从一个MysqL的例子来学习查询语句
- 从一个MysqL的例子来学习查询语句
- mysql 查询语句分析explain
- MySQL中动态生成多条件查询语句
- MySQL复制表结构和数据SQL语句
- 按时间段查询MYSQL语句
- SQL server、MySQL、Oracle分页查询SQL语句
- MySQL的一个一条SQL语句查询所有不同种类产品的一部分结果实例的SQL语句