《SQL必知必会——第12、13课:联结表、创建高级联结》

2024-08-28 13:58

本文主要是介绍《SQL必知必会——第12、13课:联结表、创建高级联结》,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       两个多月没有更新博客,有时不禁问时间都去哪儿了。似乎每个周末也没有打游戏、也没有追剧消磨时光,心里倒想着过得这么休闲、悠哉,但现实却是各种压力山大,还需继续奋斗。有点跑题了,还是说说这两课要讲的内容吧。这两课的内容说简单也简单,说复杂也复杂。简单是因为,这两课讲的内容其实就是查询操作,虽说有一些新花样,但万变不离其宗。说复杂呢,因为这次查询涉及的表数量都超过2个,也就是不在一张表上折腾了,而是同时在多张表上折腾。

       第12课 联结表

       “sql最强大的功能之一就是能在数据查询的执行中联结(join)表,联结是利用sql的select能执行的最重要的操作”。这样的表述在本书中还是很少见的,连续用了两个最字,可见联结的重要。那什么是联结呢?联结就是join,把多个表联到一起,原来select * from A,现在是select * from A,B,C,也就是同时查A表、B表、C表,如果这些表都不相干,风马牛不相及的几张表也可以放在一起查?对,都可以放在一起查,只要你认为有意义,符合你的期望,你都可以放到一起查。对于联结,千万别再字眼上较劲,理解就好。那为什么需要联结呢?因为数据库是关系型的,表是关系型的。我们在设计数据库时,相同的数据不会放在很多表中,因为这样会产生大量无意义数据,非常占地方,也不好操作。比如学生成绩表,没必要保存学生的出生年月、家庭地址等,这些信息会保存在学生基本信息表中,但是会在学生成绩表中保存学生基本信息id。这两张表通过学生基本信息id相互关联,这就是关系表,根据业务场景,将要保存的信息分解成多个表,一类数据一个表,各表通过某些共同的值相互关联,这样做的好处,显而易见是信息不会重复保存,数据一致性更好,可伸缩性也更好。下面是联结查询示例:

select vend_name, prod_name, prod_price from vendors, products where vendors.vend_id = products.vend_id;

       和以往的查询不同,这条查询from子句后面列出了两个表:vendors和products,而where子句后面查询条件是两个表中的共有字段vend_id,具体执行时,也就是联结两个表查询时,实际就是将第一个表中的每一行与第二个表中的每一行配对,where子句作为过滤条件,只包含那些匹配给定条件的行。如果没有where条件,那么可想而知,第一个表中的每一行将于第二个表中的每一行配对输出,查询结果的行数将是第一个表中的行数乘以第二个表中的行数。其结果就是笛卡尔积:假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为:{ (a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2) }。所以前面说,其实就算两个不相干的表也可以放在一起联结查询,无非结果是笛卡尔积,只要业务上能接受就行,不过,大部分业务应该不会这么干。所以要保证所有的联结都有where子句。

       联结也分很多类型,上面的示例,其实准确讲属于等值联结,它基于两个表之间的相等测试,这种联结也称为内联结。下面是上面示例的另一种写法:

select vend_name, prod_name, prod_price from vendors inner join products on vendors.vend_id = products.vend_id;

       两者查询结果一样,语句表述不一样。第一种可以称为简单语法,第二种可以称为标准语法。实际工作中用哪种,完全看个人喜好了,没有标准答案。

       下面是联结三个表的示例:

select prod_name, vend_name, prod_price, quantity 
from order_items, products, vendors 
where products.vend_id = vendors.vend_id 
and order_items.prod_id = products.prod_id
and order_num = 20007;

       这里的from子句列出三个表,where子句定义的第3个联结条件用来过滤订单20007中的物品(这条示例语句也可以用子查询来写,但需要考量性能,哪种性能好用哪种)。说白了就是将一份长的信息,合理拆解后分别保存进不同表中,查询时,通过关联字段和过滤条件,再把数据查出来。其实这里难的不是编写sql语句,而是拆解信息,需要非常熟悉业务,才能将业务数据进行合理的组织、划分,数据组织的高效,后面的业务逻辑处理也会省力很多。当然,业务数据也允许一定的冗余,因为拆分的太细,查询时势必要联结很多表,联结的表越多,性能下降越厉害,说白了就是空间换时间。

       第13课 创建高级联结

       因为使用联结,sql语句一般都很长,为了缩短sql语句,可以给表使用别名,像前面给列和计算字段使用别名一样。比如:

select cust_name, cust_contact 
from customers as c, orders as o, order_items as oi 
where c.cust_id = o.cust_id 
and oi.order_num = o.order_num
and prod_id= 'RGAN01';

       语句里面的c、o、oi就是表别名,用了别名可以缩短sql语句长度,不过不用也行,看个人喜好吧。

       使用不同类型的联结,根据业务需求,除了前面比较常见的内联接,实际还会有:自联结、自然联结、外联结

       自联结

       顾名思义,就是自己和自己联结,如下例所示:

select c1.cust_id, c1.cust_name, c1.cust_contact
from customers as c1, customers as c2
where c1.cust_name = c2.cust_name
and c2.cust_contact = 'Jim Jones'

       查询中需要的两个表实际上是相同的表,where首先联结两个表,然后按第二个表中的cust_contact过滤数据,返回所需的数据。很多场景下,可以用自联结,也可以用子查询实现,一般子查询更容易理解,但自联结性能更好。

       自然联结

       感觉没啥讲的,因为前面提到的内联结都是自然联结。自然联结就是排除返回结果中一个列多次出现, 使得每个列只返回一次。然后查询时对一个表使用通配符,而对其他表的列使用明确的子集来完成。但工作中都会控制返回的列,所以基本不会出现一个列多次出现,这种写法也就基本不会用。但知道点总是好的。

select c.*, o.order_num, oi.prod_id
from customers as c, orders as o, order_item as oi
where c.cust_id = o.cust_id
and o.order_num = oi.order_num
and oi.prod_id = 'RGAN01'

       外联结

       内联接是将一个表中的行与另一个表中的行相关联,但有时候需要包含没有关联行的那些行。示例如下:

select customers.cust_id, orders.order_num 
from customers left outer join orders 
on customers.cust_id = orders.cust_id;

       这条语句执行时, cust_id没有order_num的也会被返回。在使用outer join语法时,必须使用right或left关键字指定包括其所有行的表。right指出的是outer join右边的表,而left指出的是outer join左边的表。这是什么意思呢?前面说联结在执行时就是将第一个表中的每一行与第二个表中的每一行配对。由于外联结没有关联的行也会被输出,那么在执行时就需要指定一个表作为基准表,从基准表中取出每一行,然后在另一个表中查询符合条件的行,配对输出,如果没有匹配到,则输出null,显然left或right作用就是指定基准表。但其实无非就是表的顺序,哪个表放在outer join前面、哪个表放在outer join后面,然后可以发现通过调整表的顺序,其实left或者right只用其中一个就可以了,左就是右,右就是左。

       使用带聚集函数的联结

       其实既然已经联结,所以不管操作几个表,你都看做是操作一个大表,那么聚集函数自然可以应用到联结查询。如下例所示:

select customers.cust_id, count(orders.order_num) as num_ord 
from customers inner join orders 
on customers.cust_id = orders.cust_id
group by customers.cust_id;

       联结,也就是常说的多表查询,没啥难的,如果感觉难,那就先混个脸熟,隔几天再看,多看几次,慢慢也就理解了。

这篇关于《SQL必知必会——第12、13课:联结表、创建高级联结》的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1114959

相关文章

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

Mysql中设计数据表的过程解析

《Mysql中设计数据表的过程解析》数据库约束通过NOTNULL、UNIQUE、DEFAULT、主键和外键等规则保障数据完整性,自动校验数据,减少人工错误,提升数据一致性和业务逻辑严谨性,本文介绍My... 目录1.引言2.NOT NULL——制定某列不可以存储NULL值2.UNIQUE——保证某一列的每一

解密SQL查询语句执行的过程

《解密SQL查询语句执行的过程》文章讲解了SQL语句的执行流程,涵盖解析、优化、执行三个核心阶段,并介绍执行计划查看方法EXPLAIN,同时提出性能优化技巧如合理使用索引、避免SELECT*、JOIN... 目录1. SQL语句的基本结构2. SQL语句的执行过程3. SQL语句的执行计划4. 常见的性能优

SQL Server 中的 WITH (NOLOCK) 示例详解

《SQLServer中的WITH(NOLOCK)示例详解》SQLServer中的WITH(NOLOCK)是一种表提示,等同于READUNCOMMITTED隔离级别,允许查询在不获取共享锁的情... 目录SQL Server 中的 WITH (NOLOCK) 详解一、WITH (NOLOCK) 的本质二、工作

MySQL 强制使用特定索引的操作

《MySQL强制使用特定索引的操作》MySQL可通过FORCEINDEX、USEINDEX等语法强制查询使用特定索引,但优化器可能不采纳,需结合EXPLAIN分析执行计划,避免性能下降,注意版本差异... 目录1. 使用FORCE INDEX语法2. 使用USE INDEX语法3. 使用IGNORE IND

SQL Server安装时候没有中文选项的解决方法

《SQLServer安装时候没有中文选项的解决方法》用户安装SQLServer时界面全英文,无中文选项,通过修改安装设置中的国家或地区为中文中国,重启安装程序后界面恢复中文,解决了问题,对SQLSe... 你是不是在安装SQL Server时候发现安装界面和别人不同,并且无论如何都没有中文选项?这个问题也