SQL联结

本文介绍了SQL中的关系表设计理念,强调了数据不重复的重要性,以及如何通过建立多个相关表来提高数据处理效率。接着详细讲解了联结的概念,包括等值联结(内联结)的使用,通过实例展示了如何在SELECT语句中联结多个表以获取所需信息。最后,讨论了表别名、自联结和自然联结等高级联结技巧,强调在使用联结时要考虑性能因素。

1、关系表

理解关系表,最好是来看个例子。

有一个包含产品目录的数据库表,其中每类物品占一行。对于每一种物品,要存储的信息包括产品描述、价格,以及生产该产品的供应商。 现在有同一供应商生产的多种物品,那么在何处存储供应商名、地址、联系方法等供应商信息呢?

将这些数据与产品信息分开存储的理由是:

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

(2)如果供应商信息发生变化,例如供应商迁址或电话号码变动,只需修改一次即可;

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

关键是,相同的数据出现多次决不是一件好事,这是关系数据库设计的基础。

关系表的设计就是要把信息分解成多个表,一类数据一个表各 表通过某些共同的值互相关联(所以才叫关系数据库)。

在这个例子中可建立两个表:一个存储供应商信息,另一个存储产品信息。Vendors表包含所有供应商信息,每个供应商占一行,具有唯一的标 识。此标识称为主键(primary key),可以是供应商ID或任何其他唯一值。 Products表只存储产品信息,除了存储供应商ID(Vendors表的主键)外,它不存储其他有关供应商的信息。Vendors表的主键将Vendors表 与Products表关联,利用供应商ID能从Vendors表中找出相应供应商的详细信息。

这样做的好处是: 供应商信息不重复,不会浪费时间和空间; 如果供应商信息变动,可以只更新Vendors表中的单个记录,相关表中的数据不用改动; 由于数据不重复,数据显然是一致的,使得处理数据和生成报表更简单。 总之,关系数据可以有效地存储,方便地处理。因此,关系数据库的可伸缩性远比非关系数据库要好。

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

2、联结

联结是一种机制,用来在一条SELECT语句中关联表,因此称为联结。使用特殊的语法,可以联结多个表返回一组输 出,联结在运行时关联表中正确的行。

例:

分析:
我们来看这段代码。SELECT语句与前面所有语句一样指定要检索的列。这里最大的差别是所指定的两列(prod_name和prod_price)在一个表 中,而第三列(vend_name)在另一个表中。 现在来看FROM子句。与以前的SELECT语句不一样,这条语句的FROM子句列出了两个表:Vendors和Products。它们就是这条SELECT语句联结的两 个表的名字。这两个表用WHERE子句正确地联结,WHERE子句指示DBMS将Vendors表中的vend_id与Products表中的vend_id匹配起来。 可以看到,要匹配的两列指定为Vendors.vend_id和Products.vend_id。这里需要这种完全限定列名,如果只给出vend_id,DBMS就不知道指 的是哪一个(每个表中有一个)。从前面的输出可以看到,一条SELECT语句返回了两个不同表中的数据。

 

 

笛卡儿积(cartesian product)

由没有联结条件的表关系返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。

where子句的作用就是在笛卡尔积的结果上筛选出符合条件的

 

3、内联结

目前为止使用的联结称为等值联结(equijoin),它基于两个表之间的相等测试。这种联结也称为内联结(inner join)。其实,可以对这种联结 使用稍微不同的语法,明确指定联结的类型。下面的SELECT语句返回与前面例子完全相同的数据:

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

此语句中的SELECT与前面的SELECT语句相同,但FROM子句不同。这里,两个表之间的关系是以INNER JOIN指定的部分FROM子句。在使用这种语 法时,联结条件用特定的ON子句而不是WHERE子句给出。传递给ON的实际条件与传递给WHERE的相同。

 

SQL不限制一条SELECT语句中可以联结的表的数目。创建联结的基本规则也相同。首先列出所有表,然后定义表之间的关系。例如:

SELECT prod_name, vend_name, prod_price, quantity FROM OrderItems, Products, Vendors WHERE Products.vend_id = Vendors.vend_id AND OrderItems.prod_id = Products.prod_id AND order_num = 20007;

这个例子显示订单20007中的物品。订单物品存储在OrderItems表中。每个产品按其产品ID存储,它引用Products表中的产品。这些产品通过供 应商ID联结到Vendors表中相应的供应商,供应商ID存储在每个产品的记录中。这里的FROM子句列出三个表,WHERE子句定义这两个联结条件, 而第三个联结条件用来过滤出订单20007中的物品。

警告:性能考虑 DBMS在运行时关联指定的每个表,以处理联结。这种处理可能非常耗费资源,因此应该注意,不要联结不必要的表。联结的表越多,性能 下降越厉害。

返回订购产品RGAN01的顾客列表:方法一:

SELECT cust_name, cust_contact FROM Customers WHERE cust_id IN (SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01'));

方法二:

SELECT cust_name, cust_contact FROM Customers, Orders, OrderItems WHERE Customers.cust_id = Orders.cust_id AND OrderItems.order_num = Orders.order_num AND prod_id = 'RGAN01';

二、高级联结

1、使用表别名

SQL除了可以对列名和计算字段使用别名,还允许给表名起别名。这样做有两个主要理由: 缩短SQL语句; 允许在一条SELECT语句中多次使用相同的表

例:

SELECT cust_name, cust_contact FROM Customers AS C, Orders AS O, OrderItems AS OI WHERE C.cust_id = O.cust_id AND OI.order_num = O.order_num AND prod_id = 'RGAN01';

分析:

可以看到,FROM子句中的三个表全都有别名。Customers AS C使用C作为Customers的别名,如此等等。这样,就可以使用省略的C而不用全 名Customers。在这个例子中,表别名只用于WHERE子句。其实它不仅能用于WHERE子句,还可以用于SELECT的列表、ORDER BY子句以及其他语句 部分。

注意:表别名只在查询中使用

2、自联结

例:要在这个表customers中找与Jim Jones同一公司的所有顾客发送一封信件 

 可以看到,这个检索是在同一个表中进行了两次搜索,自联结可以给同一个表多个不同的列名,进而检索。

自联结比子查询要快

3、自然联结

自然联结使得检索得到的数据中的每一列都是唯一的,这个需要手工完成。自然联结只能选择那些唯一的列,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值