《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

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

oracle DBMS_SQL.PARSE的使用方法和示例

《oracleDBMS_SQL.PARSE的使用方法和示例》DBMS_SQL是Oracle数据库中的一个强大包,用于动态构建和执行SQL语句,DBMS_SQL.PARSE过程解析SQL语句或PL/S... 目录语法示例注意事项DBMS_SQL 是 oracle 数据库中的一个强大包,它允许动态地构建和执行

SQL 中多表查询的常见连接方式详解

《SQL中多表查询的常见连接方式详解》本文介绍SQL中多表查询的常见连接方式,包括内连接(INNERJOIN)、左连接(LEFTJOIN)、右连接(RIGHTJOIN)、全外连接(FULLOUTER... 目录一、连接类型图表(ASCII 形式)二、前置代码(创建示例表)三、连接方式代码示例1. 内连接(I

在MySQL执行UPDATE语句时遇到的错误1175的解决方案

《在MySQL执行UPDATE语句时遇到的错误1175的解决方案》MySQL安全更新模式(SafeUpdateMode)限制了UPDATE和DELETE操作,要求使用WHERE子句时必须基于主键或索引... mysql 中遇到的 Error Code: 1175 是由于启用了 安全更新模式(Safe Upd

Python创建Excel的4种方式小结

《Python创建Excel的4种方式小结》这篇文章主要为大家详细介绍了Python中创建Excel的4种常见方式,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以学习一下... 目录库的安装代码1——pandas代码2——openpyxl代码3——xlsxwriterwww.cppcns.c

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

MySql死锁怎么排查的方法实现

《MySql死锁怎么排查的方法实现》本文主要介绍了MySql死锁怎么排查的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录前言一、死锁排查方法1. 查看死锁日志方法 1:启用死锁日志输出方法 2:检查 mysql 错误

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意