代码示例7.10 内联结和WHERE子句结合使用
--指定 SQL Server DB2 PostgreSQL MySQL SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price FROM ShopProduct AS SP INNER JOIN Product AS P ON SP.product_id = P.product_id WHERE SP.shop_id = '000A';
执行结果
外联结——OUTER JOIN
代码清单7.11 将两张表进行外联结
--指定 SQL Server DB2 PostgreSQL MySQL SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price FROM ShopProduct AS SP RIGHT OUTER JOIN Product AS P ON SP.product_id = P.product_id;
执行结果
外联结要点①——选取出单张表中全部信息
可以发现外联结相对于内联结多了两条记录。多出的两条记录是高压锅和圆珠笔,这两条记录在ShopProduct表中并不存在,也就是说,这2种商品在任何商店中都没有销售。由于内联结只能选取同时存在于两张表中的数据,因此只在Product表中存在的2种商品并没有出现在结果之中。
而对于外联结来说,只要数据存在于某一张表中,就能够读取出来。
注意:在实际的业务汇总,如果想生成固定行数的单据时,就需要使用外联结,如果使用内联结的话,根据SELECT语句执行是商品库存状况的不同,结果的行数也会发生改变。
外联结要点②——每张表都是主表吗?
外联结还有一点非常重要,那就是要把那张表作为主表。最终的结果中会包含主表内所有的数据。指定主表的关键字是LEFT和RIGHT。
使用LEFT时FROM子句中写在左侧的表是主表,使用RIGHT时右侧的表是主表。
代码示例7.12 使用左外联结
--指定 SQL Server DB2 PostgreSQL MySQL SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price FROM Product AS P LEFT OUTER JOIN ShopProduct AS SP ON SP.product_id = P.product_id;
注意: 外联结中使用LEFT、RIGHT来指定主表。使用二者所得到的结果完全相同。
3张以上的表的联结
通常联结只涉及到两张表,但是有时候也会出现联结3张以上的表的情况。原则上联结表的数量并没有限制。
先创建一张用于管理库存商品的表。
CREATE TABLE InventoryProduct ( inventory_id CHAR ( 4 ) NOT NULL, product_id CHAR ( 4 ) NOT NULL, inventory_quantity INTEGER NOT NULL, PRIMARY KEY ( inventory_id, product_id ));
插入数据
--指定mysql START TRANSACTION; INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P001', '0001', 0 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P001', '0002', 120 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P001', '0003', 200 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P001', '0004', 3 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P001', '0005', 0 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P001', '0006', 99 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P001', '0007', 999 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P001', '0008', 200 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P002', '0001', 10 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P002', '0002', 25 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P002', '0003', 34 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P002', '0004', 19 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P002', '0005', 99 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P002', '0006', 0 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P002', '0007', 0 ); INSERT INTO InventoryProduct ( inventory_id, product_id, inventory_quantity ) VALUES ( 'P002', '0008', 18 ); COMMIT;
代码示例 7.14 对3张表进行内联结
--指定SQL Server DB2 PostgreSQL MySQL SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price, IP.inventory_quantity FROM ShopProduct AS SP INNER JOIN Product AS P ON SP.product_id = P.product_id INNER JOIN InventoryProduct AS IP ON SP.product_id = IP.product_id WHERE IP.inventory_id = 'P001';
执行结果
交叉联结
其实这种联结在实际业务中并不会使用,交叉联结本身非常简单,但是其结果有点麻烦。
将Product表和ShopProduct表进行交叉联结。
代码示例7.15 将两张表进行交叉联结
--指定 SQL Server DB2 PostgreSQL MySQL SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name FROM ShopProduct AS SP CROSS JOIN Product AS P;
执行结果
ShopProduct表中有11条记录,Product表存在8条记录,所以结果中包含了11*8=88条记录。交叉查询对满足相同规则的表进行交叉联结的集合运算符是CROSS JOIN(笛卡尔积)。进行交叉联结时无法使用内联结和外联结中所使用的ON子句,这是因为交叉联结是对两张表中的全部记录进行交叉组合,因此结果中的记录数通常是两张表中行数的乘积。
内联结时交叉联结的一部分,“内”可以理解为“包含在交叉联结结果中的部分”。相反,外联结“外”可以理解为“交叉联结结果之外的部分”
注意:交叉联结没有应用到实际业务之中的原因有两个。一其结果没有实用价值,二是由于其结果行数太多,需要花费大量的运算时间和高性能设备的支持。