专栏首页GreenLeavesSQL学习之联结表的使用

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 条评论
登录 后参与评论

相关文章

  • C# 移位运算符

    int result1= 66 << 1;//正数的左移位运算规则,左移一位乘以2,右移移位除以2 左移两位乘以4,三位乘以8,4位乘...

    郑小超.
  • JavaScript之firstChild属性、lastChild属性、nodeValue属性学习

    1.数组元素childNodes[0]有更直观易读的优点,这边在介绍一个有同样功能的属性,且更加语义化-------->firstChild属性 假设我们需要目...

    郑小超.
  • .Net 站点跨域问题及解决方法

    了解跨域之前, 先了解下什么同源策略? 百度百科: 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同...

    郑小超.
  • 边车设计模式-Sidecar pattern

                                                 

    sdcuike
  • 精选的10个前端开发工具...| 慕课网

    网页前端开发人员必须关注当下流行的工具,今天为了帮助前端开发者们找到好的高效的开发工具,我们转载分享了这些工具。例如:生成工具、JS库、框架和其他好...

    IMWeb前端团队
  • creator源码收集

    https://forum.cocos.com/t/cocos-creator/37765

    一枚小工
  • 开发效率太低?您可能没看这篇文章

    还记得刚参加工作的时候, 有位开发的同事软件使用效率奇高. 我曾亲眼目睹他在几秒之内打开开发软件, 优雅地调出隐藏的功能, 输入数据输出结果的过程行云流水, 一...

    鹅厂优文
  • 容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

    在OCP中,每个计算节点(默认是node节点,master节点通过配置也可以运行业务,但不建议这么做。)对于pod而言,CPU和内存都是属于计算资源。

    魏新宇
  • nginx+php-fpm出现502 bad gateway错误解决方法

    老七Linux
  • 掌握机器学习数学基础之概率统计(一)

    标题: 机器学习为什么要使用概率 概率学派和贝叶斯学派 何为随机变量和何又为概率分布? 条件概率,联合概率和全概率公式: 边缘概率 独立性和条件独立性 期望、方...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券