SQL学习之联结表的使用

1、简介:"联结(join)表"是SQL最强大的功能之一。联结是利用SQL的SELECT能执行的最重要的操作,很好地理解联结及其语法是学习SQL的极为重要的部分!

在能够有效的使用联结前,必须了解关系表以及关系型数据库设计的一些基础知识。

2、关系表

下面通过一个列子来理解关系表。

有一个包含产品目录的数据库表,其中每类物品占一行。对于每一种物品,要存储的信息包括产品描述、价格以及生产该产品的供应商。关于供应商,现在一个供应商生产多个产品,那么在何处存储供应商名、地址、联系方式等供应商信息呢?这里正确的做法是将供应商的信息和产品信息分开存储到两个表中,而分开的理由是:

(1)同一供应商生产的每个产品,其供应商信息是相同的,对每个产品重复此信息既浪费时间又浪费存储空间;

(2)如果供应商信息发生变化,只需修改一次供应商信息即可,而不需要去每个产品的信息中修改;

(3)如果有重复数据(即每种产品都存储供应商信息),则很难保证每次输入该数据的方式(也就是说输错供应商信息)都相同。不一致的数据在报表中就很难利用到;

关键是,相同的数据出现多次绝对不是一件好事,这是关系型数据库设计的基础。关系表的设计就是要把信息分解成多个表,一类数据一个表。各表之间通过某些共同的值相互关联(所以才叫关系型数据库,大多数情况下采用主键关联);

综上所述,我们建立两个表:一个存储供应商信息(Vendors),另一个存储产品信息(Products),Products表通过存储Vendors的主键实现两个表之间的通信(关联)。

这样做的好处是:

(1)供应商的信息不会重复,不会浪费时间和存储空间,每个产品只需要存储一个供应商Id,就可以通过它知道所有关于供应商的信息(前提是供应商Id要是唯一的);

(2)如果供应商的信息发生变动,只需要更新Vendors(供应商)表,相关表的数据不用改动;

(3)由于数据不重复,数据显然是一致的,使得处理数据和生成报表更简单;

总之,关系型数据库可以有效的存储,方便的处理。因此,关系型数据库的可伸缩性远比非关系数据库的要好。

可伸缩性:能够适应不断增加的工作量而不失败。设计良好的数据库或应用程序称为可伸缩性好。

3、像2中所说的将数据分解成多个表能有效的存储,更方便的处理,并且可伸缩性更好。但这些好处是有代价的。

    因为如果数据存储在多个表中,怎样用一条SELECT语句就检索出想要的数据呢?这个时候就需要使用到SQL的联结表技术了,简答的说,联结是一种机制,用来在一条SELECT语句中关联多个表,因此称为联结。使用特殊的语法,可以联结多个表返回一组输出,联结在运行时关联表中正确的行。

下面通过代码来理解联结的作用:

create database Study
go
use Study
go

create table Products
(
Id int identity(1000,1),
Name varchar(50) null,
Price decimal(4,1) null,
VendorId int null
)
insert into Products values('黑曼巴',666.6,100000)
insert into Products values('淘宝网',100.6,100001)
insert into Products values('人工智能汽车',366.6,100002)
insert into Products values('英雄联盟',166.6,100005)
insert into Products values('万达广场',66.6,100006)
select * from Products


create table Vendors
(
Id int identity(100000,1),
Name varchar(20) null,
Adress varchar(255) null,
Tel varchar(11) null
)
insert into Vendors values('Nick','America California','1111111111')
insert into Vendors values('Alibaba','Hangzhou China','2222222222')
insert into Vendors values('BaiDu','BeiJing China','3333333333')
insert into Vendors values('Tencent','ShenZheng China','44444444444')
insert into Vendors values('WanDa','DaLian China','5555555555')
select * from Vendors

这是关系库和关系表的SQL代码!

这是两个表的数据图,现在有个报表程序需要所有产品的详细信息,包括产品的名称、价格、供应商名称、供应商的地址等;

简单的分析下问题,我们发现产品的名称、价格、可以从Products表中获取,但是供应商名称、供应商的地址却需要从Vendors表中获取!这个时候我们就需要使用SQL的"联结表技术"了,下面是解决代码:

select Vendors.Name,Vendors.Adress,Products.Name,Products.Price from Vendors,Products WHERE Vendors.Id=Products.VendorId

ok,完成需求!

      下面分析下上面那段代码:首先SELECT语句和之前随笔中的SELECT语句都一样,即指定要检索的列,这里最大的差别是所指定的两列(Products.Name,Products.Price)在Products表中,而列外两列(Vendors.Name,Vendors.Adress)却在另一个表(Vendors)中,所以FROM语句和之前随笔中的不同,这里的FROM子句列出了两个表(Products表和Vendors表),最后再看WHERE子句,这里WHERE子句的作用是只是DBMS将Vendors表中的Id与Products表中的VendorId进行匹配,即Vendors表中每一行将于Products表中的每一行进行条件判断,条件是Vendors表的Id和Products表的VendorId是否相等,如果相等的话,再将两条记录进行合并(这是我个人的假想),通过SELECT语句返回对应的记录,如果不相等,则将对应的行记录过滤!

注意:如果不指定WhERE子句,相当于没有联结条件(过滤条件),那么返回的结果就是笛卡尔积,检索出的行数等于(A表的行数乘以B表的行数,从上面的流程图就可以看出)。代码如下:

select Vendors.Name,Vendors.Adress,Products.Name,Products.Price from Vendors,Products 

4、内联结

     像上面例子中的两个表的数据联结成为等值联结,它基于两个表之间的相等测试,这种联结也称为内联结,其实,可以对上面列子中的两个表之间的联结使用稍微不同的语法,明确指定联结的类型,也能完成同样的效果。下面我们通过使用内联结的语法,来获取上面列子想要的数据。代码如下:

select a.Name,a.Adress,b.Name,b.Price from Vendors a INNER JOIN Products b ON a.Id=b.VendorId

ok,完成需求!通过内联结 INNER JOIN

比较一下两种实现代码发现:两端代码的SELECT语句是一样的,但FROM子句不同,内联结的FROM子句是告诉DBMS两张表的联结方式是INNER JOIN(内联结),联结的条件是ON 子句而不是WHERE子句这也是区别于上面列子的,但实际内联结的ON 子句与WHERE子句的作用是一样的。

5、联结多个表

SQL不限制一条SELECT 语句中可以联结的表数目,但事实上,许多DBMS对此都有限制,因为DBMS在运行时关联指定的每个表,以处理联结。这种处理非常耗资源,因此在实际的开发中,应该要注意,不要联结不必要的表,联结的表越多,性能下降就越厉害!例如:

select * from 
         dbo.Products,
         dbo.Vendors,
         dbo.OrderItems 
         where Vendors.Id=dbo.Products.VendorId 
           and dbo.OrderItems.ProductId=dbo.Products.Id 
           and dbo.OrderItems.OrderId=1

这个列子显示了订单编号为1的详细信息;

通过内联结在实现一次这个需求:

select * from
         dbo.Products INNER JOIN 
         dbo.Vendors ON Vendors.Id=dbo.Products.VendorId INNER JOIN
         dbo.OrderItems ON dbo.OrderItems.ProductId=Products.Id
         where dbo.OrderItems.OrderId=1

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏阮一峰的网络日志

数据压缩与信息熵

1992年,美国佐治亚州的WEB Technology公司,宣布做出了重大的技术突破。 该公司的DataFiles/16软件,号称可以将任意大于64KB的文件,...

38250
来自专栏GreenLeaves

SQL学习之高级联结(自联结、自然联结、外联接)

create table Customers( Id int identity(1000000,1), Company varchar(30) null, Na...

27470
来自专栏数据和云

Oracle 12c 新特性:SQL Plan Directives与过量的动态采样解析

在 12c 中,优化器进行了较大的改变,推出了 Adaptive query optimization,从整体上说,Adaptive query optimiz...

13120
来自专栏Crossin的编程教室

【每周一坑】蜥蜴流感与贝叶斯定理

春季是流感的高发季节。不要觉得只是小小的“感冒”,严重起来甚至也会危及生命,而且还没有特效药。因此,身体不适请及时到医院检查。

17530
来自专栏AI科技评论

开发 | 如何利用 TVM 优化深度学习GPU op?教你用几十行Python代码实现2-3倍提升

数天前,陈天奇团队宣布推出 TVM,在微博上表示,「我们今天发布了 TVM,和 NNVM 一起组成深度学习到各种硬件的完整优化工具链,支持手机,cuda, op...

46180
来自专栏机器学习和数学

[情人节] jieba分词介绍

jieba 分词我觉得是Python中文分词工具中最好用的一个工具包。想要入门自然语言处理,jieba分词有必要好好掌握一下,今天带大家入门一下jieba分词包...

552120
来自专栏玉树芝兰

如何用Python处理自然语言?(Spacy与Word Embedding)

本文教你用简单易学的工业级Python自然语言处理软件包Spacy,对自然语言文本做词性分析、命名实体识别、依赖关系刻画,以及词嵌入向量的计算和可视化。

23010
来自专栏机器学习算法与Python学习

基于Python-ChatterBot搭建不同adapter的聊天机器人(使用NB进行场景分类)

chatterbot是一款python接口的,基于一系列规则和机器学习算法完成的聊天机器人。具有结构清晰,可扩展性好,简单实用的特点。本文通过chatterbo...

69090
来自专栏流媒体

音频编码(一)——FFmpeg编码

这里为啥讲到了声波,讲到了我们的中学物理上的知识,因为我想大家能从根本理解后面音频编码的各种参数以及原因。当然这些知识网上都能搜到,我只是整合一下。

1.9K40
来自专栏养码场

SQL 数据库查询的优化工具及实用

本文主要是对数据库查询优化器的一个综述,包括查询优化器分类、查询优化器执行过程和CBO框架Calcite。

42620

扫码关注云+社区

领取腾讯云代金券