您的位置:首页 > 数据库 > MySQL

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;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql 数据库