先附上数据

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. 面向属性的CSS命名

    自从开始做前端开发以来,我发现在开发页面的时候,总是有一个问题十分影响自己的开发效率,这个问题就是css的命名,主要是指css类选择器的命名.这个问题主要体现在:第一,有的内容你压根想不出用什么名字来 ...

  2. 获取Linux主机的CPU、内存、主板、BIOS的信息(Centos)

    #!/usr/bin/env python #coding:utf-8 import subprocess import re def Cmd_Exec(cmd): ''' 执行获取信息命令 :par ...

  3. mac下tomcat的安装与配置

    1.到 apache官方主页 下载 Mac 版本的完整 tar.gz文件包.解压拷贝到 /Library目录下,并命名为Tomcat,其他目录也可.   2.修改目录权限 到终端输入 sudo chm ...

  4. 数据结构与算法JavaScript (四) 串(BF)

    串是由零个或多个字符组成的有限序列,又叫做字符串 串的逻辑结构和线性表很相似的,不同的是串针对是是字符集,所以在操作上与线性表还是有很大区别的.线性表更关注的是单个元素的操作CURD,串则是关注查找子 ...

  5. 万能Adapter以及ViewHolder性能优化

    //CommonAdapter import android.content.Context; import android.widget.BaseAdapter; import java.util. ...

  6. EntityFramework之孩子删除(四)(你以为你真的懂了?)

    前言 从表面去看待事物视线总有点被层层薄雾笼罩的感觉,当你静下心来思考并让指尖飞梭于键盘之上,终将会拨开浓雾见青天.这是我切身体验. 在EF关系配置中,我暂且将主体对象称作为父亲,而依赖对象称作为孩子 ...

  7. ES6 - Note6:Set与Map

    Set和Map是ES6中新增的数据结构,Set是集合,无序唯一,Map类似于对象,也是"key-value"形式,但是key不局限于字符串. 1.Set的用法 Set是构造函数,可 ...

  8. CodeIgniter笔记-去掉index.php

    1.修改Apache 的配置文件把LoadModule rewrite_module modules/mod_rewrite.so该行前的#去掉. 2.将 AllowOverride None ,修改 ...

  9. Linux笔记之——Linux关机命令详解(转)

    原文连接:http://www.jb51.net/os/RedHat/1334.html 在linux下一些常用的关机/重启命令有shutdown.halt.reboot.及init,它们都可以达到重 ...

  10. 利用xinetd进行时间同步

    时间同步,往往是大型项目里一个基本的需求:如果现在有多台服务器需要时间同步为标准时间,一般有如下两种做法: 一:NTP服务 将一台能上外网的服务器配成公网时间服务器(譬如:ntp服务配置文件中的0.r ...