《Sam Teach Yourself SQL in 10 Minutes》学习笔记(3)

--联结表
--可伸缩性(scale)   能够适应不断增加的工作量而不失败。设计良好的数据库或应用程序称之为可伸缩性好(scale well)。
--如果数据存储在多个表中,怎么用SELECT语句检索出数据?    使用联结
--联结是一种机制,用来在一条SELECT语句中关联表,因此称之为连结。
--创建联结
--SELECT vend_name, prod_name, prod_price FROM Vendors, Products WHERE Vendors.vend_id = Products.vend_id;
--完全限定列名   在引用的列可能出现二义性时,必须使用完全限定列名(用一个句号分隔的表名和列名)。如果引用一个没有用表名限制的具有二义性的列名,大多数DBMS将返回错误。
--笛卡儿积(cartesian product)  由没有联结条件的表关系返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。
--SELECT vend_name, prod_name, prod_price FROM Vendors, Products;
--内部联结
--目前为止所用的联结称为等值联结(equijoin),它基于两个表之间的相等测试。这种联结也称为内部联结。对于这种联结可以使用稍微不同的语法来明确指定联结的类型。
--SELECT vend_name, prod_name, prod_price FROM Vendors INNER JOIN Products ON Vendors.vend_id = Products.vend_id;
--此语句中的SELECT与前面的SELECT语句相同,但FROM子句不同。这里,两个表之间的关系是FROM子句的组成部分,以INNER JOIN指定。在使用这种语法时,联结条件用特定的ON子句而不是WHERE子句给出。传递给ON的实际条件与传递给WHERE的相同。
--12.2.3 联结多个表
--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;
--性能考虑  DBMS在运行时关联指定的每个表以处理联结。这种处理可能是非常耗费资源的,因此应该仔细,不要联结不必要的表。联结的表越多,性能下降越厉害。
--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操作的最有效的方法。
--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';

--13  建立高级联结
--13.1 使用表别名
--SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title FROM Vendors ORDER BY vend_name;
--别名除了用于列名和计算字段外,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';																							   
--但是,表列名不仅能用于WHERE子句,它还可以用于SELECT的列表、ORDER BY子句以及语句的其他部分。
--注意:表列名只在查询执行中使用。与列别名不一样,表别名不返回客户机。
--13.2使用不同类型的联结			自联结,自然联结,外联结。
--13.2.1   自联结
--使用表别名的主要原因之一是能在单条SELECT语句中不止一次引用相同的表。
--假如能发送一封信件给位Jim Jones所在的公司工作的所有客户。此查询要求首先找出Jim Jones工作的公司,然后找出为此公司工作的客户。
--SELECT cust_id, cust_name, cust_contact FROM Customers WHERE cust_name = (
																		  --SELECT cust_name FROM Customers WHERE cust_contact = 'Jim Jones');
--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';
--为了避免二义性,使用了表别名。Customers的第一个出现为别名为c1,第二次出现为别名c2。现在可以将这些别名用作表名。例如,SELECT语句使用c1前缀明确地给出所需列的全名。如果不这样,DBMS将返回错误,因为分别存在两个名为cust_id、cust_name、cust_contact的列。DBMS不知道想要的是哪一个列(即使他们事实上是同一个列)。WHERE首先联结两个表,然后按第二个表中的cust_contact过滤数据,返回所需的数据。
--用自联结而不用子查询	自联结通常作为外部语句用来替代从相同表中检索数据的使用子查询语句。虽然最终的结果是相同的,但许多DBMS处理联结元远比处理子查询快得多。应该试一下两种方法,以确定哪一种的性能更好。
--13.2.2 自然联结
--标准的联结(前一章中介绍的内部联结)返回所有数据,甚至相同的列多次出现。自然联结排除多次出项,是每个列只返回一次。
--怎么完成这项工作呢?由自己完成。其中你只能选择那些唯一的列。这一般是通过对表使用通配符(SELECT *),对所有其它表的列使用明确的自己来完成的。
--SELECT C.*, O.order_num, O.order_date, OI.prod_id, OI.quantity, OI.item_price
--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';
--迄今为止我们建立的每个内部联结都是自然联结,很可能我们永远都不会用到不是自然联结的内部联结。
--13.2.3 外部联结
--计算平均销售规模,包括那些至今尚未下订单的客户
--这个例子中,联结包含了那些在相关表中没有关联行的行。
--SELECT Customers.cust_id, Orders.order_num FROM Customers INNER JOIN Orders ON Customers.cust_id = Orders.cust_id;		--内部联结
--SELECT Customers.cust_id, Orders.order_num FROM Customers LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id; --外部联结
--注:测试上面的两个例子,分析内部联结和外部联结的差别。
--使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包括其所有表(RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表)。上面例子使用LEFT OUTER JOIN从FROM子句的左边表(Customers表)中选择所有行。为了从右边的表中选择所有行,应该使用RIGHT OUTER JOIN,如下例所示:
--SELECT Customers.cust_id, Orders.order_num
--FROM Customers RIGHT OUTER JOIN Orders
--ON Orders.cust_id = Customers.cust_id;
--SELECT Customers.*, Orders.* FROM Customers, Orders WHERE Orders.cust_id = Customers.cust_id;
--SELECT Customers.*, Orders.* FROM Customers, Orders WHERE Customers.cust_id = '1000000002';
--SELECT Customers.*, Orders.* FROM Customers LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id;
--SELECT Orders.* FROM Orders;
--SELECT Customers.* FROM Customers;
--SELECT Orders.*, Customers.* FROM Orders INNER JOIN Customers ON Customers.cust_id = Orders.cust_id;   --分析外部联结的结果及其含义
--SELECT Customers.cust_id, Orders.order_num
--FROM Customers, Orders
--WHERE Customers.cust_id *= Orders.cust_id;		--SQL Server不支持
--*=操作符用来指定应该包括Customers表中的每一行。*=为左外部联结操作符。它从左边表中检索所有行。
--与左外部联结相对的是右外部联结,由=*指定。可用它来返回 列在操作符右边的表中所有行,如下面的例子所示: (注:SQL Server不支持)
--SELECT Customers.cust_id, Orders.order_num FROM Customers, Orders WHERE Orders.cust_id =* Customersl.cust_id;
--外部联结的类型  不管外部联结采用什么语法,总存在两种基本的外部联结形式,即:左外部联结和右外部联结。它们之间的唯一差别是所关联的表的顺序。换句话说,左外部联结可通过颠倒FROM或WHERE子句中表的顺序转换为右外部联结。因此,两种类型的外部链接可互换使用,而究竟使用哪一种纯粹是根据方便而定。
--全外部链接(full outer join),与左外部联结或右外部联结不一样(它们包含来自一个表的不关联的行),全外部链接包含来自两个表的不关联的行。全外部联结的语法如下:
--SELECT Customers.cust_id, Orders.order_num
--FROM Orders FULL OUTER JOIN Customers
--ON Orders.cust_id = Customers.cust_id;
--13.3  使用带聚集函数的联结
--聚集函数也可以与联结一起使用
--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;
--SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord        --外部联结
--FROM Customers LEFT OUTER JOIN Orders
--ON Customers.cust_id = Orders.cust_id
--GROUP BY Customers.cust_id;
--使用联结和联结条件
--注意所使用的联结类型。一般我们使用内部联结,但使用外部联结也是有效的。
--保证使用正确的联结条件(不管是采用哪种语法),否则将返回不正确的数据。
--应该总是提供联结条件,否则会得出笛卡儿积。
--在一个联结中可以包含多个表,甚至对于每个联结可以不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前,分别测试每个联结。这将使故障排除更为简单。











 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值