`

sql之多表查询

    博客分类:
  • sql
阅读更多

笛卡尔乘积 :

	当一个连接条件无效或被遗漏时,其结果是一个笛卡尔乘积 (Cartesian product),其中所有行的组合都被显示。第一个表中的所有行连接到第二个表中的所有行。 
	一个笛卡尔乘积会产生大量的行,其结果没有什么用。你应该在 WHERE 子句中始终包含一个有效的连接条件,除非你有特殊的需求,需要从所有表中组合所有的行。 
	对于一些测试笛卡尔乘积是有用的,例如你需要产生大量的行来模拟一个相当大的数据量。 

多表查询(Displaying Data from Multiple Tables):

    JOIN:

       SQL 的连接(JOIN)语句将数据库中的两个或多个表组合起来,由"连接"生成的集合, 可以被保存为表, 或者当成表来使用. JOIN 语句的含义是把两张表的属性通过它们的值组合在一起.

    基于 ANSI 标准的 SQL 列出了四种 JOIN 方式: 内连接(INNER), 外连接(OUTER), 左外连接(LEFT), 右外连接(RIGHT).在特定的情况下, 一张表(基本表, 视图, 或连接表)可以和自身进行连接, 成为自连接(self-join).

内连接(inner join):

    一般都是默认的连接类型. 将两张表(如 A 和 B)的列组合在一起, 产生新的结果表. 查询会将 A 表的每一行和 B 表的每一行进行比较, 并找出满足连接词的组合. 当连接词被满足, A 和 B 中匹配的行会按列组合(并排组合)成结果集中的一行. 连接产生的结果集, 可以定义为首先对两张表做笛卡尔积(交叉连接) -- 将 A 中的每一行和 B 中的每一行组合, 然后返回满足连接谓词的记录. 实际上 SQL 产品会尽可能用其他方式去实现连接, 笛卡尔积运算是非常没效率的,可以进一步被分为: 相等连接, 自然连接, 和交叉连接.

 

	SQL 定义了两种不同语法方式去表示"连接". 首先是"显示连接符号", 它显式地使用关键字 JOIN, 其次是"隐式连接符号". 隐式连接符号把需要连接的表放到 SELECT 语句的 FROM 部分, 并用逗号隔开. 这样就构成了一个"交叉连接", WHERE 语句可能放置一些过滤谓词(过滤条件). 那些过滤谓词在功能上等价于显式连接符号.

 例如:

        下面的查询通过 Employee 表和 Department 表共有的属性 DepartmentID 连接两表. 在两表 DepartmentID 匹配之处(如连接谓词被满足), 查询将组合两表的 LastName, DepartmentID 和DepartmentName 等列, 把它们放到结果表的一行(一条记录)里. 当 DepartmentID 不匹配, 就不会往结果表中生成任何数据.

 

        --显式的内连接实例:
	select e.EmployeeId,e.LastName,d.部門,d.DepartmentId FROM Employee as e INNER JOIN Department as d ON e.DepartmentID = d.DepartmentId

 等价于:

select e.EmployeeId,e.LastName,d.部門,d.DepartmentId FROM Employee as e,Department as d where e.DepartmentID = d.DepartmentId

     相等链接 (equi-join, 或 equijoin):是比较连接的一种特例, 它的连接词只用了相等比较. 使用其他比较操作符(如 <)的不是相等连接.

        实例:

	--SQL 提供了一种可选的简短符号去表达相等连接, 它使用 USING 关键字:
	select e.EmployeeId,e.LastName,d.部門,d.DepartmentId FROM Employee as e INNER JOIN Department as d USING(DepartmentId)

     USING 结构并不仅仅是语法糖(指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。), 上面查询的结果和使用显式谓词得到的查询得到的结果是不同的. 特别地, 在 USING 部分列出的列(column)将以只出现一次, 且名称无表名修饰.在上面的例子中, 将产生单独的名为 DepartmentID 的列, 而不是 employee.DepartmentID 或 department.DepartmentID.

     自然连接: 自然连接比相等连接的进一步特例化. 两表做自然连接时, 两表中的所有名称相同的列都将被比较, 这是隐式的. 自然连接得到的结果表中, 两表中名称相同的列只出现一次.

--上面用于内连接的查询实例可以用自然连接的方式表示如下:
SELECT * FROM Employee NATURAL JOIN Department

用了 USING 语句后, 在连接表中, DepartmentID 列只出现一次, 且没有表名作前缀:

      在 Oracle 里用 JOIN USING 或 NATURAL JOIN 时, 如果两表共有的列的名称前加上某表名作为前缀, 则会报编译错误: "ORA-25154: column part of USING clause cannot have qualifier" 或 "ORA-25155: column used in NATURAL join cannot have qualifier".

     交叉连接(cross join): 又称笛卡尔连接(cartesian join)或叉乘(Product), 它是所有类型的内连接的基础. 把表视为行记录的集合, 交叉连接即返回这两个集合的笛卡尔积. 这其实等价于内连接的链接条件为"永真", 或连接条件不存在.

    用于交叉连接的 SQL 代码在 FROM 列出表名, 但并不包含任何过滤的连接谓词.

	--显式的交叉连接实例:
		SELECT * FROM   Employee CROSS JOIN Department
	--隐式的交叉连接实例:
		SELECT * FROM   Employee, Department

 外连接:

    外连接并不要求连接的两表的每一条记录在对方表中都一条匹配的记录. 连接表保留所有记录 -- 甚至这条记录没有匹配的记录也要保留. 外连接可依据连接表保留左表, 右表或全部表的行而进一步分为左外连接, 右外连接和全连接.(在这种情况下left<左> 和 right<右> 表示 JOIN 关键字的两边.)在标准的 SQL 语言中, 外连接没有隐式的连接符号.

左外连接:

    左外连接(left outer join), 亦简称为左连接(left join), 若 A 和 B 两表进行左外连接, 那么结果表中将包含"左表"(即表 A)的所有记录, 即使那些记录在"右表" B 没有符合连接条件的匹配. 这意味着即使 ON 语句在 B 中的匹配项是0条, 连接操作还是会返回一条记录, 只不过这条记录的中来自于 B 的每一列的值都为 NULL. 这意味着左外连接会返回左表的所有记录和右表中匹配记录的组合(如果右表中无匹配记录, 来自于右表的所有列的值设为 NULL). 如果左表的一行在右表中存在多个匹配行, 那么左表的行会复制和右表匹配行一样的数量, 并进行组合生成连接结果.

   如, 这允许我们去找到雇员的部门时, 显示所有雇员, 即使这个雇员还没有关联的部门. (在上面的内连接部分由一个相反的例子, 没有关联的部门号的雇员在结果中是不显示的).

        --左外连接实例: (相对于内连接增添的行用斜体标出)
	SELECT *  FROM   Employee  LEFT OUTER JOIN Department  ON Employee.DepartmentID = Department.DepartmentId 

 

右外连接:

       右外连接, 亦简称右连接, 它与左外连接完全类似, 只不过是作连接的表的顺序相反而已. 如果 A 表右连接 B 表, 那么"右表" B 中的每一行在连接表中至少会出现一次. 如果 B 表的记录在"左表" A 中未找到匹配行, 连接表中来源于 A 的列的值设为 NULL.右连接操作返回右表的所有行和这些行在左表中匹配的行(没有匹配的, 来源于左表的列值设为 NULL).

      例如, 这允许我们在找每一个雇员以及他的部门信息时, 当这个部门里没有任何雇员时, 也把部分显示出来.

--右连接的实例: (相对于内连接增添的行用斜体标出)
SELECT * FROM   Employee RIGHT OUTER JOIN Department ON Employee.DepartmentID = Department.DepartmentID
--实际上显式的右连接很少使用, 因为它总是可以被替换成左连接--换换表的位置就可以了, 另外, 右连接相对于左连接并没有什么额外的功能. 上表同样可以使用左连接得到:
SELECT * FROM   Department LEFT OUTER JOIN Employee ON Employee.DepartmentID = Department.DepartmentID

全连接:

    全连接是左右外连接的并集. 连接表包含被连接的表的所有记录, 如果缺少匹配的记录, 即以 NULL 填充.如, 这允许我们查看每一个在部门里的员工和每一个拥有雇员的部门, 同时, 还能看到不在任何部门的员工以及没有任何员工的部门.

    全连接实例:

SELECT *  FROM   Employee  FULL OUTER JOIN Department ON Employee.DepartmentID = Department.DepartmentID
 
--一些数据库系统(如 MySQL)并不直接支持全连接, 但它们可以通过左右外连接的并集(参: union)来模拟实现. 和上面等价的实例:

SELECT *
FROM   Employee 
       LEFT JOIN Department 
          ON Employee.DepartmentID = Department.DepartmentID

SELECT *
FROM   Employee
       RIGHT JOIN Department
          ON Employee.DepartmentID = Department.DepartmentID
WHERE  Employee.DepartmentID IS NULL

 自连接:

    自连接就是和自身连接;

    构建一个查询, 它试图找到这样的记录: 每条记录包含两个雇员, 他们来自于同一个国家. 如果你有两张雇员表(Employee), 那么只要第一张表的雇员和第二张表的雇员在同样的国家的就行了, 你可以用一个通常的连接(相等连接)操作去得到这个表. 不过, 这里所有雇员信息都在一张但对大表里.

SELECT 
e.EmployeeId,
e.LastName,
e.DepartmentID,
e.Country,
f.EmployeeId,
f.LastName,
f.DepartmentID,
f.Country
FROM Employee f,Employee e
WHERE f.Country = e.Country
AND e.EmployeeId<f.EmployeeId
ORDER BY e.EmployeeId,f.EmployeeId;

 关于这个例子, 请注意:

    * F 和 S 是雇员表(employee)的第一个和第二个拷贝的别名
    * 条件 F.Country = S.Country 排除了在不同国家的雇员的组合. 这个例子仅仅期望得到在相同国家的雇员的组合.
    * 条件 F.EmployeeID < S.EmployeeID 排除了雇员号(EmployeeID)相同的组合.
    * F.EmployeeID < S.EmployeeID 排除了重复的组合. 没有这个条件的话, 将生成类似下面表中的无用数据

 

替代方式
    外连接查询得到的结果也可以通过关联子查询得到. 例如:

SELECT 
e.LastName, 
e.DepartmentID,
Department.部門
FROM  Employee e 
LEFT OUTER JOIN Department
ON e.DepartmentID = Department.DepartmentId

 还可以这样:

SELECT 
e.LastName, 
e.DepartmentID,
(SELECT Department.部門 FROM Department
WHERE e.DepartmentID = Department.DepartmentId)
FROM  Employee e
 

 

 

分享到:
评论

相关推荐

    SQL数据库多表查询练习题

    通过这些练习,你不仅可以提升SQL查询技能,还能更好地理解和应用数据库设计原理,这对于数据库管理员、数据分析师或任何与数据打交道的职业来说都是至关重要的。记住,理论学习只是第一步,实践才能让你真正掌握...

    WinForm+SQL多表联合自定义查询

    本示例中的“WinForm+SQL多表联合自定义查询”是一个结合了两者的技术,允许用户通过WinForm界面进行自定义的多表联合查询。在实际开发中,这样的功能对于数据检索和分析至关重要,特别是在处理大型复杂数据库时。 ...

    SQL查询(多表查询)

    SQL查询 多表查询,学习left 、right等操作

    Excel中SQL多表查询

    Excel中SQL多表查询

    SQL多表联合查询.rar

    描述中提到“使用时只需重新选择数据源的位置”,这可能是指在某些应用程序或开发环境中,例如使用VB(Visual Basic)开发的数据库应用,需要指定数据源连接信息来执行SQL查询。在这个例子中,我们看到“student.mdb...

    浅谈Linq to sql 的多表关联与动态条件查询

    浅谈Linq to sql 的多表关联与动态条件查询 Linq to sql 是一种强大的数据查询语言,它可以帮助开发者快速、高效地访问和操作数据库数据。在本文中,我们将讨论 Linq to sql 的多表关联和动态条件查询这两个重要的...

    sql语句学习 多表连接查询

    自己学习的笔记--查询计算机系CS男学生学号、姓名和考试成绩 SELECT A.Sno,A.Sname,B.degree FROM student A,sc B WHERE A.Sdept = 'CS' AND A.Ssex = '男' AND A.Sno = B.sno SELECT A.Sno,A.Sname,B.degree FROM ...

    Visual C++源代码 158 如何获取SQL语句多个查询结果表

    Visual C++源代码 158 如何获取SQL语句多个查询结果表Visual C++源代码 158 如何获取SQL语句多个查询结果表Visual C++源代码 158 如何获取SQL语句多个查询结果表Visual C++源代码 158 如何获取SQL语句多个查询结果表...

    查询表空间sql

    查询表空间sql

    SQL多表连接查询优化的相关研究

    标题中的“SQL多表连接查询优化的相关研究”指的是在数据库管理中,如何高效地执行涉及多个数据表的SQL查询操作。在SQL(Structured Query Language)中,连接查询(JOIN)是用于合并两个或更多表中的数据的关键技术...

    Oracle sql语句多表关联查询

    Oracle SQL 语句多表关联查询 Oracle SQL 语句多表关联查询是数据库管理系统中的一种常见查询方式,它可以从多个表中检索数据,满足业务需求。本文将详细介绍 Oracle SQL 语句多表关联查询的知识点,包括字符串和...

    sqlserver之并行查询

    SQL Server 之并行查询 并行查询是 SQL Server 中的一种查询优化技术,通过使用多个线程来处理查询作业,从而提高查询的效率。这种技术可以加速查询的执行速度,特别是在大表查询和复杂查询的情况下。 一、并行...

    SQL多表连接

    本文档为通用SQL数据库查询时所用,讲述的是多表连接!~

    SQL server数据库单表查询

    该文档详细描述了SQL server环境下数据库单表查询的sql语句的编写

    sqlserver 根据内容,查询表和列名字

    sqlserver 根据字段内容,查询表和列名字 sqlserver 根据字段内容,查询表和列名字 sqlserver 根据字段内容,查询表和列名字 sqlserver 根据字段内容,查询表和列名字 sqlserver 根据字段内容,查询表和列名字

    oracle SQL查询工具

    oracle SQL查询工具oracle SQL查询工具oracle SQL查询工具oracle SQL查询工具oracle SQL查询工具oracle SQL查询工具oracle SQL查询工具oracle SQL查询工具oracle SQL查询工具oracle SQL查询工具oracle SQL查询工具...

    省市区sql文件 单表 支持级联查询

    省市区sql文件 单表

    SQL语句多表查询

    一、外连接 1、左连接 left join 或 left outer join 2、右连接 right join 或 right outer join 3、完全外连接 full join 或 full outer join ...四、两表关系为一对多,多对一或多对多时的连接语句

    VB编程源代码 71一次SQL查询中获得多个查询数值

    VB编程源代码 71一次SQL查询中获得多个查询数值VB编程源代码 71一次SQL查询中获得多个查询数值VB编程源代码 71一次SQL查询中获得多个查询数值VB编程源代码 71一次SQL查询中获得多个查询数值VB编程源代码 71一次SQL...

    数据库实验报告 SQL查询 ,子查询组合

    【SQL查询与子查询组合】 SQL (Structured Query Language) 是用于管理和处理数据库的标准语言,而SQL Server 2000是Microsoft提供的一款关系型数据库管理系统。在这个实验中,你将学习如何使用SQL Server 2000的...

Global site tag (gtag.js) - Google Analytics