数据库学习第四天之多表查询
2016-11-03 11:07
288 查看
表与表之间的关系包含以下几种:
1)1对1(示例:一夫一妻)
2)1对多,多对1(一个人可以拥有多辆汽车,要求查询出某人所拥有的所有汽车。)
3)多对多(一个人可以拥有多种角色,如某人,即是父亲、又是儿子、又是丈夫。而同时这三个角色又可以给其他所有的人。
)
使用关联查询和子查询:
当一个表的数据不能满足我们的需要时,我们就要从多个表中查询数据。此时必须使用关联查询:
inner join – 内关联,双方必须都要存在。
left join -左关联。以左边数据为准。
right join - 右关联。
1)1对1(示例:一夫一妻)
2)1对多,多对1(一个人可以拥有多辆汽车,要求查询出某人所拥有的所有汽车。)
3)多对多(一个人可以拥有多种角色,如某人,即是父亲、又是儿子、又是丈夫。而同时这三个角色又可以给其他所有的人。
)
使用关联查询和子查询:
当一个表的数据不能满足我们的需要时,我们就要从多个表中查询数据。此时必须使用关联查询:
inner join – 内关联,双方必须都要存在。
left join -左关联。以左边数据为准。
right join - 右关联。
SHOW VARIABLES LIKE 'character%'; //多表关系----第一种:一对一关系! //躲表建立1对1关系----注意保证外键字段唯一! //创建男人表 CREATE TABLE man( id VARCHAR(32) PRIMARY KEY, NAME VARCHAR(30) ); //创建女人表---失败品 CREATE TABLE woman( id VARCHAR(32) PRIMARY KEY, NAME VARCHAR(30), husband VARCHAR(32), CONSTRAINT wm_fk FOREIGN KEY(husband) REFERENCES man(id) ); //上面这个表创建出来是1对多的关系,但是由于外键那不是唯一的 DROP TABLE woman; CREATE TABLE woman( id VARCHAR(32) PRIMARY KEY, NAME VARCHAR(30), husband VARCHAR(32) UNIQUE, CONSTRAINT wm_fk FOREIGN KEY(husband) REFERENCES man(id) ); //往表中插入行数据 INSERT INTO man VALUES('1','张三'); INSERT INTO man VALUES('2','李四'); INSERT INTO man VALUES('3','王五'); INSERT INTO man VALUES('4','王大发'); //往woman表中插入行数据 INSERT INTO woman VALUES('1','小花','1'); INSERT INTO woman VALUES('2','玉芬','2'); INSERT INTO woman VALUES('3','王大嫂','4'); //查询出所有的夫妻关系 //第一种插询方式 SELECT man.name 丈夫,woman.NAME 妻子 FROM man INNER JOIN woman ON man.id=woman.husband; //第二种查询方式 SELECT m.name AS 丈夫,w.name AS 妻子 FROM man AS m INNER JOIN woman AS w ON m.id=w.husband; //查询出光棍 SELECT man.name FROM man LEFT JOIN woman ON woman.husband IS NULL; SELECT man.name AS 光棍 FROM man LEFT JOIN woman ON woman.husband=man.id WHERE woman.id IS NULL; //由于外键是相对于主表中的主键而言,所以外键的值必须包含在主表的主键值范围内!所以woman表中的所有女人必须对应一个丈夫!没有寡妇 ------------------ 二、1对多 ※第三范式: 1方建主表(id为主键字段), 多方建外键字段(pid--参考主表的主键id,不加UNIQUE) //创建人表 CREATE TABLE person( id VARCHAR(32) PRIMARY KEY, NAME VARCHAR(30), sex CHAR(1) DEFAULT '0' ); //创建汽车表 CREATE TABLE car( id VARCHAR(32) PRIMARY KEY, NAME VARCHAR(30), price NUMERIC(6,2), pid VARCHAR(32), CONSTRAINT car_fk FOREIGN KEY(pid) REFERENCES person(id) ); //往两个表中插入相关的行数据 INSERT INTO person VALUES('1','Jack','0'); INSERT INTO person VALUES('2','张三','0'); INSERT INTO person VALUES('3','Rose玫瑰','1'); INSERT INTO person VALUES('4','机械先驱','0'); INSERT INTO person VALUES('5','克洛克达尔','1'); INSERT INTO car VALUES('C001','宝马A系',40.5,'1'); INSERT INTO car VALUES('C002','BenZB系',56.6,'1'); INSERT INTO car VALUES('C003','QQ',4.54,'1'); INSERT INTO car VALUES('C004','Audi',5.56,'2'); INSERT INTO car VALUES('C005','Horse',85.2,'4'); INSERT INTO car VALUES('C007','广汽一众',3.65,'4'); //外键字段可以为NULL INSERT INTO car(id,NAME,price) VALUES('C006','fentian',22.0); //◇查询哪些人有哪些车 SELECT * FROM person INNER JOIN car ON person.id=car.pid; SELECT person.name,car.name,car.price FROM person INNER JOIN car ON person.id=car.pid; //◇查询Jack有哪些车 SELECT person.name,car.name,car.price FROM person INNER JOIN car ON person.id=car.pid WHERE person.name='jack'; //◇查询哪些人有两辆或两辆以上的车 //根据题目的意思我并不觉得这是失败品! SELECT person.name FROM person INNER JOIN car ON person.id=car.pid GROUP BY car.pid HAVING COUNT(car.pid)>=2; //第二种理解意思(连人带车都给列举出来,上面那种是不行的!) SELECT person.name,car.name,car.price FROM person INNER JOIN car ON person.id=car.pid WHERE person.id IN('1','4') ; //将上面的id字段写活! SELECT person.id FROM person INNER JOIN car ON person.id=car.pid GROUP BY car.pid HAVING COUNT(car.pid)>=2; //将上面两步合起来即可达到演示效果! SELECT car.name,car.price,person.name FROM person INNER JOIN car ON person.id=car.pid WHERE person.id IN (SELECT person.id FROM person INNER JOIN car ON person.id=car.pid GROUP BY car.pid HAVING COUNT(car.pid)>=2); //精简做法 SELECT car.name,car.price,person.name FROM car INNER JOIN person ON person.id=car.pid WHERE person.id IN (SELECT pid FROM car GROUP BY pid HAVING COUNT(pid)>=2) ORDER BY person.name DESC; ============ //综上所述!一定要时时刻刻想到IN(子查询)---很关键!内连接也很关键! ============ //◇查询哪些人没有车(左连接) SELECT person.name 姓名,(CASE sex WHEN '0' THEN '男' WHEN '1' THEN '女' ELSE '其他' END) 性别 FROM person LEFT JOIN car ON person.id=car.pid WHERE car.id IS NULL; //试着删除汽车编号为C001的汽车(删除成功) DELETE FROM car WHERE id='C001'; //试着删除编号为1的jack车主(删除失败!因为两个表之间有关联!person表中关联了car表中的数据,所有删除时要格外小心!) DELETE FROM person WHERE id='1'; ------------------------------- //3.演示多对多的关系! 三、多对多( 3个表= 2个实体表 + 1个关系表 ) ※第三范式: 两个实体都建成独立的主表, 另外再单独建一个关系表(采用联合主键) 1、分别建议两个实体表(没有外键,但有自己的主键, 没有冗余信息) CREATE TABLE stud( id VARCHAR(32) PRIMARY KEY, NAME VARCHAR(30) ); CREATE TABLE ject( id VARCHAR(32) PRIMARY KEY, NAME VARCHAR(30) ); //再建一个独立的表!(注意建表时不指定外键!建完表之后再指定!) CREATE TABLE sj( studid VARCHAR(32) NOT NULL, jectid VARCHAR(32) ); //在指定外键的时候注意一个易错的小细节!先建联合主键再建外键! //下面演示是错的! ALTER TABLE sj ADD CONSTRAINT sj_fk1 FOREIGN KEY(studid) REFERENCES stud(id); ALTER TABLE sj ADD CONSTRAINT sj_fk2 FOREIGN KEY(jectid) REFERENCES ject(id); ALTER TABLE sj ADD CONSTRAINT sj_pk PRIMARY KEY(studid,jectid); //下面是正确的演示 ALTER TABLE sj DROP FOREIGN KEY sj_fk1; ALTER TABLE sj DROP FOREIGN KEY sj_fk2; ALTER TABLE sj ADD CONSTRAINT sj_pk PRIMARY KEY(studid,jectid); ALTER TABLE sj ADD CONSTRAINT sj_fk1 FOREIGN KEY(studid) REFERENCES stud(id); ALTER TABLE sj ADD CONSTRAINT sj_fk2 FOREIGN KEY(jectid) REFERENCES ject(id); 3、添加一些演示数据 //实体表1 INSERT INTO stud VALUES('S001','Jack'); INSERT INTO stud VALUES('S002','Rose'); INSERT INTO stud VALUES('S003','Tom'); INSERT INTO stud VALUES('S004','张三'); //实体表2 INSERT INTO ject VALUES('J001','Java'); INSERT INTO ject VALUES('J002','Oracle'); INSERT INTO ject VALUES('J003','XML'); INSERT INTO ject VALUES('J004','JSP'); INSERT INTO ject VALUES('J005 bcad ','Game'); //关系表 INSERT INTO sj VALUES('S001','J001'); INSERT INTO sj VALUES('S001','J003'); INSERT INTO sj VALUES('S001','J004'); INSERT INTO sj VALUES('S002','J002'); INSERT INTO sj VALUES('S002','J003'); INSERT INTO sj VALUES('S002','J004'); //查询哪些人选了哪些课 //SQL组织的1992标准,可用,但效率不高 SELECT stud.name 学生,ject.name 课程 FROM stud,sj,ject WHERE stud.id=sj.studid AND sj.jectid=ject.id; //SQL组织的1996标准,效率高,推荐使用---关联 SELECT stud.name 学生,ject.name 课程 FROM stud INNER JOIN sj ON stud.id=sj.studid INNER JOIN ject ON ject.id=sj.jectid; //查询哪些人没选课(左,又连接) SELECT stud.name FROM stud LEFT JOIN sj ON stud.id=sj.studid LEFT JOIN ject ON sj.jectid=ject.id WHERE ject.id IS NULL; //查询哪些课没人选 SELECT ject.name 课程 FROM stud RIGHT JOIN sj ON sj.studid=stud.id RIGHT JOIN ject ON ject.id=sj.jectid WHERE stud.id IS NULL; //第二种查法 SELECT ject.name 课程 FROM ject LEFT JOIN sj ON sj.jectid=ject.id LEFT JOIN stud ON stud.id=sj.studid WHERE stud.id IS NULL;
相关文章推荐
- 数据库学习二:连接中子查询括号问题
- 数据库学习笔记(二)---SQL查询语句
- 两次SQL 学习之感悟——数据库查询语言——走进数据系列之十二
- 学习数据库―― 写出高质量、高性能的MySQL查询
- 学习数据库必须掌握的54条SQL查询语句
- 学习数据库:SqlServer 2005之查询第m至第n条记录
- 五、Oracle数据库之学习笔记---Oracle的表的基本查询(2)
- JasperReport学习笔记4-查询数据库生成动态的报表(WEB)
- 黑马程序员_学习日记49_618数据库开发及ADO.Net(多条件搜索、case…when…语句、索引Index、子查询、分页、Join语句)
- C#学习笔记(六)-使用ADO .NET查询和操作数据库
- [转]十天学习PHP之第四天(PHP)----学会连接数据库
- 数据库学习一:查询工资前三高包括重复的人
- C# - 反射学习,附带绑定实体类从数据库查询数据中,带源码学习!
- JasperReport学习笔记4-查询数据库生成动态的报表(WEB)
- ACCP学习旅程之-----使用C#开发数据库应用程序(第七章 用ADO.NET查询和操作数据库)
- s数据库之多表查询
- 学习ContentProvider---之一:查询数据库
- 学习第四天@Linq查询
- 数据库学习实践(四、五)--分页浏览、查询数据
- 四、Oracle数据库之学习笔记---Oracle的表的基本查询(1)