先附上数据

CREATE TABLE `course` (
`cno` int(11) NOT NULL,
`cname` char(30) CHARACTER SET utf8 NOT NULL,
`ctime` int(11) NOT NULL,
`scount` int(11) NOT NULL,
`ctest` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `course` VALUES ('', '应用数学基础', '', '', '2016-03-10 10:08:29');
INSERT INTO `course` VALUES ('', '生物工程概论', '', '', '2016-03-10 10:09:24');
INSERT INTO `course` VALUES ('', '计算机软件基础', '', '', '2016-03-10 10:09:47');
INSERT INTO `course` VALUES ('', '计算机硬件基础', '', '', '2016-03-10 10:10:28');
INSERT INTO `course` VALUES ('', '模拟电路设计', '', '', '2016-04-06 10:11:02');
INSERT INTO `course` VALUES ('', '机械设计实践', '', '', '2016-03-10 10:11:29');
INSERT INTO `course` VALUES ('', '生物化学', '', '', '2016-03-29 10:11:54');
INSERT INTO `course` VALUES ('', '数据库设计', '', '', '2016-03-10 10:12:14');
INSERT INTO `course` VALUES ('', '设计理论', '', '', '2016-03-10 10:12:33');
INSERT INTO `course` VALUES ('', '计算机入门', '', '', '2016-03-10 10:12:53');
INSERT INTO `course` VALUES ('', '数字电路设计基础', '', '', '2016-03-10 10:13:10'); CREATE TABLE `student` (
`sno` char(4) CHARACTER SET utf8 DEFAULT NULL,
`sname` char(10) CHARACTER SET utf8 DEFAULT NULL,
`dname` char(10) CHARACTER SET utf8 DEFAULT NULL,
`ssex` char(2) CHARACTER SET utf8 NOT NULL,
`cno` int(11) NOT NULL,
`mark` decimal(3,1) NOT NULL,
`type` char(4) CHARACTER SET utf8 NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `student` VALUES ('', '刘建国', '管理工程', '男', '', '82.5', '必修');
INSERT INTO `student` VALUES ('', '刘建国', '管理工程', '男', '', '70.0', '必修');
INSERT INTO `student` VALUES ('', '刘建国', '管理工程', '男', '', '78.5', '选修');
INSERT INTO `student` VALUES ('', '李春', '环境工程', '女', '', '63.0', '必修');
INSERT INTO `student` VALUES ('', '李春', '环境工程', '女', '', '58.0', '选修');
INSERT INTO `student` VALUES ('', '王天', '生物', '男', '', '48.5', '必修');
INSERT INTO `student` VALUES ('', '王天', '生物', '男', '', '86.0', '选修');
INSERT INTO `student` VALUES ('', '李华', '计算机', '女', '', '76.0', '必修');
INSERT INTO `student` VALUES ('', '李华', '计算机', '女', '', '92.0', '必修');
INSERT INTO `student` VALUES ('', '李华', '计算机', '女', '', '89.0', '必修');
INSERT INTO `student` VALUES ('', '李华', '计算机', '女', '', '80.0', '必修');
INSERT INTO `student` VALUES ('', '李华', '计算机', '女', '', '70.0', '选修');
INSERT INTO `student` VALUES ('', '孙庆', '电子工程', '男', '', '79.0', '必修');
INSERT INTO `student` VALUES ('', '孙庆', '电子工程', '男', '', '59.0', '必修');
INSERT INTO `student` VALUES ('', '孙庆', '电子工程', '男', '', '52.0', '必修');
INSERT INTO `student` VALUES ('', '孙庆', '电子工程', '男', '', '68.0', '必修');
INSERT INTO `student` VALUES ('', '高伟', '机械工程', '男', '', '93.0', '必修');
INSERT INTO `student` VALUES ('', '高伟', '机械工程', '男', '', '88.5', '必修');
INSERT INTO `student` VALUES ('', '高伟', '机械工程', '男', '', '78.0', '选修');
INSERT INTO `student` VALUES ('', '高伟', '机械工程', '男', '', '76.0', '选修'); CREATE TABLE `teacher` (
`tno` int(11) NOT NULL,
`tname` varchar(10) CHARACTER SET utf8 NOT NULL,
`cno` int(11) NOT NULL,
`sal` int(11) DEFAULT NULL,
`dname` char(10) CHARACTER SET utf8 NOT NULL,
`tsex` char(2) CHARACTER SET utf8 NOT NULL,
`age` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO `teacher` VALUES ('', '王军', '', '', '数学', '男', '');
INSERT INTO `teacher` VALUES ('', '李丹', '', '', '生物', '女', '');
INSERT INTO `teacher` VALUES ('', '王永军', '', '', '计算机', '男', '');
INSERT INTO `teacher` VALUES ('', '刘小静', '', '', '计算机', '女', '');
INSERT INTO `teacher` VALUES ('', '高伟', '', '', '电子工程', '男', '');
INSERT INTO `teacher` VALUES ('', '李伟', '', '', '机械工程', '男', '');
INSERT INTO `teacher` VALUES ('', '刘辉', '', '', '生物', '女', '');
INSERT INTO `teacher` VALUES ('', '刘静', '', '', '经济管理', '女', '');
INSERT INTO `teacher` VALUES ('', '李伟', '', null, '计算机', '女', '');
INSERT INTO `teacher` VALUES ('', '刘一凯', '', null, '计算机', '女', '');

简单的二表连接

SELECT tname,dname,cname,ctest from teacher,course WHERE teacher.cno=course.cno
该语句的执行过程实例可以表示这样:
a,系统首先执行from子句,这里from子句列出有两个表teacher表和course表,DBMS讲计算这两个表的笛卡尔积,列出这两个表中行的所以可能组合,形成一个中间表。中间表中的每条记录包含了两个表中的所有行。
b,然后系统执行where子句,根据teacher.cno=course.cno关系对中间表进行搜索,去除那些不满足该关系的记录。
c,最后系统执行select语句,从执行where子句后得到的中间表的每条记录中,提取tname,dname,cname,ctest4个字段的信息作为结果表。
 
 
需要强调,表的连接所依据的关系是在where子句中定义的。在实际应用中,用户要实现表的连接必然要依据一定的关系。
 
 
如果不指明连接关系,即不使用where子句。
SELECT tname,dname,cname,ctest from teacher,course
        
从结果可以看到,每个教师的信息均与所有课程信息进行了匹配连接。它实际返回连接表中所有数据行的笛卡尔积,其结果集合中的数据行数等于第一个表中符合查询条件的数据行乘以第二个表中符合查询条件的数据行数,即10X11=110条记录。

采用join关键字建立连接

        也可以在from子句中,通过连接关键字实现表的连接,这样有助于将连接操作与where的搜索条件区分开来。
SELECT COLUMN from join_table join_type join_table on (join_condition)
 
join_type为连接类型,可分为4种:自然连接,内连接,外连接和交叉连接。
 

自连接

自连接是指表与其自身进行连接,这需要使用表别名。
查询成绩中存在不及格课程的学生的姓名,所在系,所有的课程及成绩信息
SELECT s.sname,s.dname,s.cno,s.mark
from student s
where s.mark<60
无法得到想要结果
 
 
SELECT s.sname,s.dname,s.cno,s.mark
from student s
where s.sno in(SELECT DISTINCT s.sno from student s where s.mark<60)
得到想要结果
 
 
SELECT DISTINCT s.sname,s.dname,s.cno,s.mark
from student s,student s2
where s.sno=s2.sno
and s2.mark<60
from子句中的两个表实际上都是表student。为了独立地使用它们,采用表别名方法。
 
SELECT s.sname,s.dname,s.cno,s.mark
from student s,student s2
where s.sno=s2.sno
and s2.mark<60
系统首先执行from子句,将student表S1与它自身S2的笛卡尔积,作为中间表。
实际上,该中间表的每一条记录包含两部分信息,一部分是S1的记录,一部分是S2的记录。而后执行where子句,在中间表中,搜索S2中成绩低于60的学生的记录,同时要求记录中S1与S2是同一个学生的记录即学号相同。最后执行select语句,从中间表获取S1中相应的信息作为结果表。
 
当执行where子句,从中间表中逐条搜索S2中成绩低于60的学生的记录时,由于孙庆有两门课程不及格,所以对每门不及格的记录都满足搜索条件,因此导致从S1得到的信息中出现了重复的记录。
 
简单来说,中间表是没有重复记录的,但是S1部分字段是有重复的,而结果集提取的只是S1部分的字段,因此就有可能有重复记录。
 
一般情况,自连接也可以使用子查询的方式实现。
 
 
SELECT DISTINCT s.sname,s.dname,s.cno,s.mark
from student s,student s2
where s.sno=s2.sno
and s.mark<60
 

自然连接

它将表中具有相同名称的列自动进行记录匹配,自然连接不必指定任何同等连接条件。
自然连接自动判断相同名称的列,而后形成匹配。缺点是,虽然可以指定查询结果包括哪些列,但是不能人为地指定哪些列被匹配。另外,自然连接的一个特点是连接后的结果表中匹配的列只有一个。如上,在自然连接后的表中只有一列C。
 
 
从student表和teacher表中查询学生姓名,所在系,所修的本系教师开设的课程的课程号以及开课教师姓名。这时候就采用natural join对两个表进行自然连接。
SELECT sname,dname,cno,tname
from student NATURAL join teacher
等价
SELECT sname,s.dname,s.cno,tname
from student s, teacher t
where s.dname=t.dname
and s.cno=t.cno

事实上,使用基于where子句的等值连接要比使用natural join运算符进行自然连接要灵活的多。
正如前面介绍的,使用natural join运算符自动判断出具有相同名称的列,而后形成匹配,不能人为地指定哪些列被匹配。当自然连接student和teacher表时,CNO和dname列同时被匹配,而不能只匹配一列。
 
 
 

外连接

不管是内连接还是带where子句的多表查询,都组合自多个表,并生成结果表。换句话说,如果任何一个源表中的行在另一个源表中没有匹配,DBMS将把该行放在最后的结果表中。
 
而外连接告诉ODBC生成的结果表,不仅包含符合条件的行,而且还包含左表(左外连接时),右表(右外连接时)或两个边接表(全外连接)中所有的数据行。
 
 
SQL的外连接共有三种类型:左外连接,右外连接,全外连接。
 

1,左外连接

左外连接,left outer join ,告诉DBMS生成的结果表中,除了包括匹配行外,还包括join关键字(from子句中)左边表的不匹配行。
左外连接实际可以表示为:
左外连接=内连接+左边表中失配的元组。
其中,缺少的右边表中的属性值用null表示。如下:
SELECT s.sno,sname,s.cno,cname,ctest,mark
from student s LEFT JOIN course c
on s.cno=c.cno
ORDER BY sname
 

右外连接

右外连接,right outer join ,告诉DBMS生成的结果表中,除了包括匹配行外,还包括join关键字(from子句中)右边表的不匹配行。
右外连接实际可以表示为:
右外连接=内连接+右边表中失配的元组。
其中,缺少的左边表中的属性值用null表示。如下:
SELECT s.sno,sname,s.cno,cname,ctest,mark
from student s RIGHT JOIN course c
on s.cno=c.cno
ORDER BY sname

全外连接

全外连接,full outer join,告诉DBMS生成的结果表中,除了包括匹配行外,还包括join关键字(from子句中)左边表和右边表的不匹配行。
可以这样表示:
全外连接=内连接+左边表中失配的元组+右边表中失配的元组
 
SELECT s.sno,sname,s.cno,cname,ctest,mark
from student s full OUTER JOIN course c
on s.cno=c.cno
ORDER BY sname
 
本人使用mysql数据库,因为mysql暂时还不支持全外连接full的功能.
 
 一些语句流程顺序,等我有空回顾在写把。等我。勿急躁。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

mysql,SQL标准,多表查询中内连接,外连接,自然连接等详解之查询结果集的笛卡尔积的演化的更多相关文章

  1. Python中内置的日志模块logging用法详解

    logging模块简介 Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用.这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/P ...

  2. SQL语句 删除表user 中字段name 内容重复的记录,

    public class T01 { public static void main(String[] args) { int j=4; j=j+=j-=j*=j; System.out.printl ...

  3. mysql status关键字 数据表设计中慎重使用

    mysql status关键字  数据表设计中慎重使用

  4. MySQL慢查询(二) - pt-query-digest详解慢查询日志 pt-query-digest 慢日志分析

    随笔 - 66 文章 - 0 评论 - 19 MySQL慢查询(二) - pt-query-digest详解慢查询日志 一.简介 pt-query-digest是用于分析mysql慢查询的一个工具,它 ...

  5. Mysql高手系列 - 第9篇:详解分组查询,mysql分组有大坑!

    这是Mysql系列第9篇. 环境:mysql5.7.25,cmd命令中进行演示. 本篇内容 分组查询语法 聚合函数 单字段分组 多字段分组 分组前筛选数据 分组后筛选数据 where和having的区 ...

  6. MySQL中的主键,外键有什么作用详解

    MySQL中的主键,外键有什么作用详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 学关系型数据库的同学,尤其在学习主键和外键时会产生一定的困惑.那么今天我们就把这个困惑连根拔起 ...

  7. Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解

    随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...

  8. SQL Server时间粒度系列----第4节季、年时间粒度详解

    本文目录列表: 1.SQL Server季时间粒度2.SQL Server年时间粒度 3.总结语 4.参考清单列表   SQL Serve季时间粒度       季时间粒度也即是季度时间粒度.一年每3 ...

  9. 转载~kxcfzyk:Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解

    Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解   多线程c语言linuxsemaphore条件变量 (本文的读者定位是了解Pthread常用多线程API和Pthread互斥锁 ...

随机推荐

  1. Atitit 分区后的查询  mysql分区记录的流程与原理

    Atitit 分区后的查询  mysql分区记录的流程与原理 1.1.1. ibd是MySQL数据文件.索引文件1 1.2. 已经又数据了,如何分区? 给已有的表加上分区 ]1 1.3. 分成4个区, ...

  2. oracle 备份数据库对象(存储过程PROCEDURE,FUNCTION,VIEW,TRIGGER...)

    开发过程中,需要不停的备份数据库对象, 特别是存储过程, 每次手动备份不免很低能啊 历经几次修改终于, 完美了,O(∩_∩)O哈哈~      (当然,你也可以再改简便一点~~~) select db ...

  3. 考勤系统——代码分析datagrid

    datagrid是easyui的控件,DataGrid以表格形式展示数据,并提供了丰富的选择.排序.分组和编辑数据的功能支持.DataGrid的设计用于缩短开发时间,并且使开发人员不需要具备特定的知识 ...

  4. KnockoutJS 3.X API 第六章 组件(3) 组件绑定

    组件绑定将指定的组件注入到元素中,并且可选地将参数传递给它. 本节目录 一个例子 API 组件生命周期 备注1:仅限模板组件 备注2:使用没有容器元素的组件 备注3:将标记传递给组件 处置和内存管理 ...

  5. 对Big Table进行全表更新,导致 Replication 同步数据的过程十分缓慢

    在Publisher database中更新一个big table,数据行数是3.4亿多.由于没有更新 clustered Index key,因此,只产生了3.4亿多个Update Commands ...

  6. Ado net Source 用法

    Ado net Source 是用于获取数据源的,使用的connection manager是 ado net connection. Ado Net Source 的Data Access Mode ...

  7. 准备 KVM 实验环境 - 每天5分钟玩转 OpenStack(3)

    KVM 是 OpenStack 使用最广泛的 Hypervisor,本节介绍如何搭建 KVM 实验环境 安装 KVM 上一节说了,KVM 是 2 型虚拟化,是运行在操作系统之上的,所以我们先要装一个 ...

  8. xUnit安装及注意事项

    前言 对于单元测试,想必大家都已再熟悉不过了,同时单元测试的重要性也越发突出,在招聘中也特别强调单元测试,但是对于微软内置的单元测试还是太过于繁琐,于是都在寻找一种简洁并且更加轻量的测试工具.用的最多 ...

  9. ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

    为了加强安全性,MySQL5.7为root用户随机生成了一个密码,在error log中,关于error log的位置,如果安装的是RPM包,则默认是/var/log/mysqld.log. 一般可通 ...

  10. EntityFramework 7 开发纪录

    博文目录: 暂时开发模式 Code First 具体体现 DbContext 配置 Entity 映射关联配置 Migration 问题纪录(已解决) 之前的一篇博文:EF7 Code First O ...