表的基本连接

    SQL的一个重要特性就是能通过JOIN关键词,从多个交叉表中查询、分析数据。

  连接表的目的

    在关系数据库中,数据表设计的一个重要原则就是要避免冗余性。

    1. 减少了冗余信息,节省了数据库存储空间。
    2. 简化了数据修改、维护操作。

  学习本节需要的数据表:

CREATE TABLE TEACHER
(
ID INT IDENTITY (,) PRIMARY KEY , --主键,自增长
TNO INT NOT NULL, --教工号
TNAME CHAR() NOT NULL, --教师姓名
CNO INT NOT NULL, --课程号
SAL INT, --工资
DNAME CHAR() NOT NULL, --所在系
TSEX CHAR() NOT NULL, --性别
AGE INT NOT NULL --年龄
)
INSERT INTO dbo.TEACHER VALUES( ,'王军',,,'数学','男',)
INSERT INTO dbo.TEACHER VALUES( ,'李彤',,,'生物','女',)
INSERT INTO dbo.TEACHER VALUES( ,'王永军',,,'计算机','女',)
INSERT INTO dbo.TEACHER VALUES( ,'刘晓婧',,,'计算机','女',)
INSERT INTO dbo.TEACHER VALUES( ,'高维',,,'电子工程','男',)
INSERT INTO dbo.TEACHER VALUES( ,'李伟',,,'机械工程','女',)
INSERT INTO dbo.TEACHER VALUES( ,'刘辉',,,'生物','女',)
INSERT INTO dbo.TEACHER VALUES( ,'刘伟',,,'计算机','男',)
INSERT INTO dbo.TEACHER VALUES( ,'刘静',,,'经济管理','男',)
INSERT INTO dbo.TEACHER VALUES( ,'刘奕锴',,,'计算机','女',)
INSERT INTO dbo.TEACHER VALUES( ,'高维',,,'经济管理','男',) CREATE TABLE COURSE
(
ID INT IDENTITY (,) PRIMARY KEY , --主键,自增长
CNO INT NOT NULL, --课程号
CNAME CHAR() NOT NULL, --课程名称
CTIME INT NOT NULL, --学时
SCOUNT INT NOT NULL, --容纳人数
CTEST SMALLDATETIME NOT NULL, --考试时间
)
INSERT INTO dbo.COURSE VALUES( ,'应用数学基础',,,'2006-7-10')
INSERT INTO dbo.COURSE VALUES( ,'生物工程概论',,,'2006-7-8')
INSERT INTO dbo.COURSE VALUES( ,'计算机软件基础',,,'2006-7-8')
INSERT INTO dbo.COURSE VALUES( ,'计算机硬件基础',,,'2006-6-28')
INSERT INTO dbo.COURSE VALUES( ,'模拟电路设计',,,'2006-7-10')
INSERT INTO dbo.COURSE VALUES( ,'机械设计实践',,,'2006-7-14')
INSERT INTO dbo.COURSE VALUES( ,'生物化学',,,'2006-7-2')
INSERT INTO dbo.COURSE VALUES( ,'数据库设计',,,'2006-7-1')
INSERT INTO dbo.COURSE VALUES( ,'设计理论',,,'2006-6-30')
INSERT INTO dbo.COURSE VALUES( ,'计算机入门',,,'2006-6-29')
INSERT INTO dbo.COURSE VALUES( ,'数字电路设计基础',,,'2006-6-20')
CREATE TABLE STUDENT
(
ID INT IDENTITY(,) PRIMARY KEY NOT NULL,
SNO CHAR() NOT NULL, --学号
SNAME CHAR() NOT NULL, --姓名
DNAME CHAR() NOT NULL, --系
SSEX CHAR() NOT NULL, --性别
CNO INT , --课程号
MARK DECIMAL(,), --成绩
TYPE CHAR() --课程类型
)
INSERT INTO dbo.STUDENT VALUES('','刘建国','管理工程','男',,82.5,'必修')
INSERT INTO dbo.STUDENT VALUES('','刘建国','管理工程','男',,,'选修')
INSERT INTO dbo.STUDENT VALUES('','刘建国','管理工程','男',,78.5,'选修')
INSERT INTO dbo.STUDENT VALUES('','李春','环境工程','女',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','李春','环境工程','女',,,'选修')
INSERT INTO dbo.STUDENT VALUES('','王天','生物','男',,48.5,'必修')
INSERT INTO dbo.STUDENT VALUES('','王天','生物','男',,,'选修')
INSERT INTO dbo.STUDENT VALUES('','李华','计算机','女',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','李华','计算机','女',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','李华','计算机','女',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','李华','计算机','女',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','李华','计算机','女',,,'选修')
INSERT INTO dbo.STUDENT VALUES('','孙庆','电子工程','男',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','孙庆','电子工程','男',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','孙庆','电子工程','男',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','孙庆','电子工程','男',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','高伟','机械工程','男',,,'必修')
INSERT INTO dbo.STUDENT VALUES('','高伟','机械工程','男',,88.5,'必修')
INSERT INTO dbo.STUDENT VALUES('','高伟','机械工程','男',,,'选修')
INSERT INTO dbo.STUDENT VALUES('','高伟','机械工程','男',,,'选修')

数据表

  1、简单的二表连接

SELECT TNAME,DNAME,CNAME,CTEST FROM dbo.TEACHER,dbo.COURSE WHERE dbo.TEACHER.CNO=dbo.COURSE.CNO   --查询老师和系表的数据

 

  根据以上SQL,可知道执行过程:

    • 系统首先执行FROM子句,这里FROM子句列出的有两个表TEACHER和COURSE,DBMS将计算这两个表的笛卡儿积,列出这两个表中行的所有可能组合,形成一个中间表。中间表的每条记录包含了两个表中的所有行。
    • 而后系统将执行WHERE子句,根据“dbo.TEACHER.CNO=dbo.COURSE.CNO”关系对中间表进行搜索,去除那些不满足该条件的记录。
    • 最后系统执行SELECT语句,从执行WHERE子句后得到的中间表的每条记录中,提取TNAME,DNAME,CNAME,CTEST这4个字段的信息作为结果表。

  注意:

    由于两张表都存在相同的字段CNO,所以在查询的时候要指明来自哪张表,如dbo.TEACHER.CNO、dbo.COURSE.CNO,而其他具有重名的字段,也要进行同样的处理,否则会报错。

  问题:

    表的连接时一句关系WHERE子句来定义的,实际开发中,也一定更要用到关系连接。如果不指明连接关系呢?

    SELECT TNAME,DNAME,CNAME,CTEST FROM dbo.TEACHER,dbo.COURSE
SELECT COUNT(*) AS 总条数 FROM dbo.TEACHER,dbo.COURSE --查询一共有几条数据

    

  2、三表查询(在WHERE子句中进行夺标查询)

SELECT SNAME,dbo.STUDENT.SNAME,CNAME,CTEST,MARK,dbo.TEACHER.TNAME FROM dbo.TEACHER,dbo.COURSE,dbo.STUDENT WHERE dbo.TEACHER.CNO=dbo.COURSE.CNO AND dbo.COURSE.CNO=dbo.STUDENT.CNO

  使用别名,S,T,C
SELECT SNAME,S.SNAME,CNAME,CTEST,MARK,TNAME FROM dbo.TEACHER AS T,dbo.COURSE AS C,dbo.STUDENT AS S WHERE T.CNO=C.CNO AND C.CNO=S.CNO
  

  ”dbo.TEACHER.CNO=dbo.COURSE.CNO AND dbo.COURSE.CNO=dbo.STUDENT.CNO“,含义为”只有同时存在TEACHER,STUDENT,COURSE“中CNO的信息才会作为结果显示出来。

  注意:

    由于学生表和老师表都有字段”DNAME“,在SELECT子句中查询DNAME字段时,我们要指定表名,否则系统会报错。

  可见,创建表的基本连接,只要遵守下面的基本原则即可:

    • FROM子句中应列出所有连接的表的表名。
    • WHERE子句应定义连接的关联条件。
    • 当列名为多个表共有时,要指明列的所在表,即采用”表名.字段名“的形式。

  3、采用JOIN关键字建立连接

SELECT COLUMN
FROM join_table
JOIN_TYPE join_table
ON (join_condition)

    说明如下:

      • join_table指出参与连接操作的表名。
      • JOIN_TYPE为连接类型,可分为四种:自然连接、内连接、外连接和交叉连接。
        • 自然连接JOIN_TYPE的形式为NATURAL JOIN
        • 内连接JOIN_TYPE的形式为INNER JOIN
        • 外连接,又分为左连接,JOIN_TYPE形式为LEFT OUTER JOIN或LEFT JOIN;右连接,JOIN_TYPE的形式为RIGHT OUTER JOIN或RIGHT JOIN;全外连接,JOIN_TYPE的形式为CROSS JOIN;全外连接,JOIN_TYPE的形式为FULL OUTER JOIN或FULL JOIN。
        • 交叉连接中JOIN_TYPE的形式为CROSS JOIN。
      • ON(join_condition)子句指出连接条件,由被连接表中的列和比较远算符、逻辑运算符等构成。

  

  4、表的连接类型

    4.1、自连接

SELECT DISTINCT SNO FROM dbo.STUDENT WHERE MARK<  --查询不及格学生学号,重复的去除
SELECT DNAME,MARK,SNAME,CNO FROM dbo.STUDENT WHERE SNO IN('','','') AND MARK < --查询三个学号中不及格学生的信息

  

    4.2、内连接(INNER JOIN)

      内连接也称为等同连接,返回的结果集是两个表中所有相匹配的数据,而舍弃不匹配的数据。查询的结果表包含的两源表行,必须满足ON子句中的搜索条件。

        使用等于号(=)比较被连接列的列值,在查询结果中列出被连接表中的所有列,包括其中的重复列。图给出了典型的等值内连接示意图。

SELECT s.SNAME,s.DNAME,s.CNO,t.TNAME FROM dbo.STUDENT AS s inner join dbo.TEACHER AS t ON t.CNO = s.CNO  --查询两表部分信息
使用不等连接进行查询  后面会讲到各种运算符 先给官方网站地址:http://www.runoob.com/sqlite/sqlite-operators.html
SELECT s.SNAME,s.DNAME,s.CNO,t.TNAME FROM dbo.STUDENT AS s inner join dbo.TEACHER AS t ON s.DNAME<>t.DNAME AND t.CNO = s.CNO
等价于:
SELECT s.SNAME,s.DNAME,s.CNO,t.TNAME FROM dbo.STUDENT AS s,dbo.TEACHER AS t WHERE s.DNAME<>t.DNAME AND t.CNO = s.CNO
DBMS默认多表查询按INNER JOIN来执行,除非指定OUTER JOIN。

 

    注意:

      INNER JOIN可以实现夺标查询,但是一次只能连接两张表,要连接多表,必须进行多次连接。

      4.2.1、使用INNER JOIN实现多表连接

--三张表进行查询,用两个INNER JOIN
SELECT s.SNAME,s.DNAME,c.CNAME,c.CTEST,s.MARK,t.TNAME FROM dbo.TEACHER AS t INNER JOIN dbo.COURSE AS c ON c.CNO = t.CNO INNER JOIN dbo.STUDENT AS s ON s.CNO = t.CNO

    4.3、外连接(OUTER JOIN)

      左外连接=内连接+左边表中失配的元组

      右外连接=内连接+右边表中失配的元组

      全外连接=内连接+左边表中失配的元组+右边表中失配的元组

      表达式示意图如:

      

SELECT s.SNO,s.SNAME,c.CNO,c.CNAME,c.CTEST,s.MARK FROM dbo.STUDENT AS s LEFT OUTER JOIN dbo.COURSE AS c ON c.CNO = s.CNO
在WHERE子句中用”*=“实现左外连接
SELECT s.SNO,s.SNAME,c.CNO,c.CNAME,c.CTEST,s.MARK FROM dbo.STUDENT AS s,dbo.COURSE AS c WHERE c.CNO *= s.CNO
----三种连接方式都一样,只需要改”LEFT OUTER JOIN“为”RIGHT OUTER JOIN“和”FULL OUTER JOIN“,
    就不做三个演示了,可以自己对比数据的异同

 

    

     4.4、交叉连接(CROSS JOIN)

       除了在FROM子句中使用逗号间隔连接的表外,SQL还支持另一种被称为交叉连接的操作,它们都返回被连接的两个表所有数据行的笛卡尔积,返回到的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。惟一的不同在于,交叉连接分开列名时,使用CROSS JOIN关键字而不是逗号。     

实际上,下面两个表达式是等价的。
SELECT * FROM table1, table2
SELECT * FROM table1 CROSS JOIN table2

       交叉连接示意图:

         

SELECT s.SNO,s.SNAME,c.CNO,s.CNO,c.CNAME,c.CTEST,s.MARK FROM dbo.STUDENT AS s CROSS JOIN dbo.COURSE AS c WHERE s.CNO=c.CNO AND s.MARK>

      注意:

        在使用CROSS JOIN关键字交叉连接表时,因为生成的是两个表的笛卡尔积,因而不能使用ON关键字,只能在WHERE子句中定义搜索条件。

      事实上,直接使用CROSS JOIN很少得到想要的结果,但是,正如实例所示,作为查询的第一步,DBMS通常在FROM子句中,对连接的表进行CROSS JOIN,然后过滤得到的中间表。

Sql Server的艺术(四) SQL多表查询的更多相关文章

  1. 数据库SQL Server2012笔记(四)——多表查询、子查询、分页查询、用查询结果创建新表和外连接

    1.多表查询 1)笛卡尔集: select  *  from  表名1,表名2 select  *  from  表名1.表名2  where   表名1.字段名=表名2.字段名 注: 若有两张表有同 ...

  2. SQL Server进阶(三)单表查询

    示例数据库 点我下载 一条完整的sql语句 select top | distinct 字段, 表达式, 函数, ... from 表表达式 where 筛选条件 group by 分组条件 havi ...

  3. SQL server分页的四种方法

    SQL server分页的四种方法 1.三重循环: 2.利用max(主键); 3.利用row_number关键字: 4.offset/fetch next关键字 方法一:三重循环思路  先取前20页, ...

  4. 从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点)

    从0开始搭建SQL Server AlwaysOn 第四篇(配置异地机房节点) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www ...

  5. SQL Server 2008 R2中,变表的右键弹出菜单中的“选择前1000行”为“选择所有行”

    原文:SQL Server 2008 R2中,变表的右键弹出菜单中的"选择前1000行"为"选择所有行" 从SQL Server 2008开始,微软为了提高查询 ...

  6. 何查询SQL Server数据库没有主键的表并增加主键

    SQL Server数据库中,如果一个表没有主键,我们该如何查询呢?本文我们主要就介绍了如何查询数据库中没有主键的表名并为其增加主键的方法,希望能够对您有所帮助. 该功能的实现代码如下: declar ...

  7. SQL server学习(四)T-SQL编程之事务、索引和视图

    今天来分享下T-SQL高级编程中的事务.索引.视图,可以和之前的SQL server系列文章结合起来. 一.事务 事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个 ...

  8. SQL SERVER 判断是否存在数据库、表、列、视图

    SQL SERVER 判断是否存在数据库.表.列.视图 --1. 判断数据库是否存在 IF EXISTS (SELECT * FROM SYS.DATABASES WHERE NAME = '数据库名 ...

  9. SQL SERVER学习笔记:临时表与表变量

    本文主要摘自徐海蔚的<Microsoft SQL SERVER企业级平台管理实践> 表变量可以作为存储过程的返回参数,而临时表不行.(存疑?表值参数只在SQL SERVER2008才开始支 ...

  10. .net(C#数据库访问) Mysql,Sql server,Sqlite,Access四种数据库的连接方式

    便签记录Mysql,Sql server,Sqlite,Access四种数据库的简单连接方式 //using MySql.Data.MySqlClient; #region 执行简单SQL语句,使用M ...

随机推荐

  1. 利用 html2canvas 做个简单的诗词卡片生成器

    html2canvas 简介 html2canvas 顾名思义,就是一个可以把 DOM 元素转换成图片的类库,常用于网页截图.网页截图常见的应用场景是,在意见反馈里对当前页面进行截图,方便反馈页面出现 ...

  2. Quartz 代码调用Demo

    一般项目中Quartz都是直接在配置文件中配置,但是一些特殊的情况需要在代码中控制,本文为代码调用的Demo,仅供参考.更多详细的Quartz配置信息,请查看: JAVA定时任务实现的几种方式 mav ...

  3. 读了前半本<Thinking in Java>

    读了1-14章.这本书真的不适合初学者,可能比较适合有一两年Java经验的人来读.学习真的是一个螺旋递进的过程.刚开始学Java基本语法,书上看到的很多东西觉得过于细枝末节,没见过,用不上,导致书看不 ...

  4. python对pywifi模块的认识

    pywifi是一个用来搞wifi的模块 下一章我们将用他破解wifi密码 pywifi安装 pip install pywifi 下列代码判断是否有无限网卡 import pywifi import ...

  5. sqlmap完成简单的sql注入

    扫描目标站点,是否存在注入 --users获取用户名 --dump --tables探测表和数据库信息 跑出来的字段 admin --dump -T admin -C admin,password暴库 ...

  6. deeplearning.ai 神经网络和深度学习 week2 神经网络基础 听课笔记

    1. Logistic回归是用于二分分类的算法. 对于m个样本的训练集,我们可能会习惯于使用for循环一个个处理,但在机器学习中,是把每一个样本写成一个列向量x,然后把m个列向量拼成一个矩阵X.这个矩 ...

  7. Cup(二分)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2289 hdu_2289:Cup Time Limit: 3000/1000 MS (Java/Othe ...

  8. 微信小程序监听input输入并取值

    小程序的事件分为两种,冒泡和非冒泡事件,像<form/>的submit事件,<input/>的input事件,<scroll-view/>的scroll事件等非冒泡 ...

  9. [OpenCV学习笔记2][Mat数据类型和操作]

    [Mat数据类型和基本操作] ®.运行环境:Linux(RedHat+OpenCV3.0) 1.Mat的作用: Mat类用于表示一个多维的单通道或者多通道的稠密数组.能够用来保存实数或复数的向量.矩阵 ...

  10. 利用PHPExcel导出Excel并设置Excel格式以及数据源

    浏览:23969 发布日期:2013/07/24 分类:技术分享 代码有点长,读起来有点累.先来个截图 导出的Excel太宽了,所以将后面的列宽重新调整了再截的图 功能包括: 1.设置单元格格式,包括 ...