先附上数据

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. [大数据之Spark]——Transformations转换入门经典实例

    Spark相比于Mapreduce的一大优势就是提供了很多的方法,可以直接使用:另一个优势就是执行速度快,这要得益于DAG的调度,想要理解这个调度规则,还要理解函数之间的依赖关系. 本篇就着重描述下S ...

  2. c#设计模式-适配器模式

    一. 适配器(Adapter)模式 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作. 名称由来 这很像变压器(Adapter),变压 ...

  3. easyui 日期显示

    { field: 'UpdateDatetime', title: '更新时间', width: 100, align: 'left', sortable: true , formatter: fun ...

  4. 【最后的抒情】【离NOIP还有9个小时】

    学了NOIP 大概十一个月左右,中途的插班生.从2015年12月底开始学信息竞赛,在寒假的时候还笑着我还有九个月才考试呢,生竞就只有两个月了.没错我是从生物竞赛转过来的.记得当初写申请的时候,写的理由 ...

  5. distribution 中一直在运行 waitfor delay @strdelaytime 语句

    Replication 自动创建来一个 Job:Replication monitoring refresher for distribution,这个Agent执行一个sp: dbo.sp_repl ...

  6. SQL Server 默认跟踪(Default Trace)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 基础知识(Rudimentary Knowledge) 查看默认跟踪信息(Default Tr ...

  7. 简单生成svg文件

    this.fileSaveSync = function (file, data) { var fs = require('fs-extra'); fs.writeFileSync(file, dat ...

  8. Android启动模式

    在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...

  9. 跌倒了,再爬起来:ASP.NET 5 Identity

    "跌倒了"指的是这一篇博文:爱与恨的抉择:ASP.NET 5+EntityFramework 7 如果想了解 ASP.NET Identity 的"历史"及&q ...

  10. ViewStub的使用

    ViewStub是一个不可见的.大小为0的控件,运行时ViewStub可以滞后加载.当ViewStub置为可见或者调用inflate()的时候,布局就会加载出来.用加载进来的布局取代ViewStub在 ...