正确地找到列
当你将TABLE1 与TABLE2 联合以后你使用SELECT * 来选择了表中的所有列在
联合表ORDER 和PART 时SELECT 看起来不太好懂
SELECT O.ORDEREDON O.NAME O.PARTNUM P.PARTNUM P.DESCRIPTION
SQL 可以知道ORDEREDON 和NAME 是在ORDER 表中而DESCRIPTION 则存在于
PART 表中但是PARTNUM 呢它在两个表中都有啊如果你想使用在两个表中都存在
的列你必须使用别名来说明你想要的是哪一列常用的办法为每一个表分配一个简单的
字符就像你在FROM 子句中所做的那样
FROM ORDERS O PART P
你可以在每一列中都使用这个字符就像你刚才在SELECT 中所做的那样SELECT
子句也可以写成下边的形式
SELECT ORDEREDON NAME O.PARTNUM P.PARTNUM DESCRIPTION
可是不要忘记有时你会不得不回过头来对查询进行维护所以让它更具有可读性并
没有什么害处还是不要使用这种省略的形式吧
SQL 21 日自学通(V1.0) 翻译人笨猪
126
等值联合
下边的表是ORDERS 与PARTS 表的联合结果的片断作为缺货的情况
30-JUN-1996 TRUEWHEEL 42 54 PEDALS
30-JUN-1996 BIKESPEC 54 54 PEDALS
30-MAY-1996 BIKESPEC 10 54 PEDALS
注意到PARTNUM 是两个表的共有字段如果输入如下的语句会有什么结果呢
INPUT
SELECT O.ORDEREDON O.NAME O.PARTNUM P.PARTNUM P.DESCRIPTION
FROM ORDERS O PART P WHERE O.PARTNUM P.PARTNUM
OUTPUT
ORDEREDON NAME PARTNUM PARTNUM DESCRIPTION
1-JUN-1996 AAA BIKE 10 10 TANDEM
30-MAY-1996 BIKE SPEC 10 10 TANDEM
2-SEP-1996 TRUE WHEEL 10 10 TANDEM
1-JUN-1996 LE SHOPPE 10 10 TANDEM
30-MAY-1996 BIKE SPEC 23 23 MOUNTAIN BIKE
15-MAY-1996 TRUE WHEEL 23 23 MOUNTAIN BIKE
30-JUN-1996 TRUE WHEEL 42 42 SEATS
1-JUL-1996 AAA BIKE 46 46 TIRES
30-JUN-1996 BIKE SPEC 54 54 PEDALS
1-JUL-1996 AAA BIKE 76 76 ROAD BIKE
17-JAN-1996 BIKE SPEC 76 76 ROAD BIKE
19-MAY-1996 TRUE WHEEL 76 76 ROAD BIKE
11-JUL-1996 JACKS BIKE 76 76 ROAD BIKE
17-JAN-1996 LE SHOPPE 76 76 ROAD BIKE
分析
利用在两个表中都存在的PARTNUM 列我们得到了存储在ORDERS 表中的的信息
以及在PARTS 中的与ORDERS 相关的信息它表明了你已经定出的零件数量这种联合
操作称为等值联合因为它只显示第一个表中的数据以及第二个表中的存在于第一个表
中的数值
你也可以使用WHERE 子句对其结果进行更大的限制例如
INPUT/OUTPUT
SELECT O.ORDEREDON O.NAME O.PARTNUM P.PARTNUM P.DESCRIPTION
SQL 21 日自学通(V1.0) 翻译人笨猪
127
FROM ORDERS O PARTP WHERE O.PARTNUM P.PARTNUM
AND O.PARTNUM=76
ORDEREDON NAME PARTNUM PARTNUMDES DESCRIPTION
1-JUL-1996 AAABIKE 76 76 ROADBIKE
17-JAN-1996 BIKESPEC 76 76 ROADBIKE
19-MAY-1996 TRUEWHEEL 76 76 ROADBIKE
11-JUL-1996 JACKSBIKE 76 76 ROADBIKE
17-JAN-1996 LESHOPPE 76 76 ROADBIKE
PARTNUM 为76 的零件描述不是非常准确你不想把它作为零件出售我们非常愦憾
在发现在许多数据库系统中需要最终用户知道一些非常晦涩的代码而该代码所代表的东
西原本就有着自己的非常清楚明白的名字请不要像他们那样做这一行代码也可以
写成如下方式
INPUT/OUTPUT
SELECT O.ORDEREDON O.NAME O.PARTNUM P.PARTNUM P.DESCRIPTION
FROM ORDERS O PART P WHERE O.PARTNUM P.PARTNUM
AND P.DESCRIPTION ROAD BIKE
ORDEREDON NAME PARTNUM PARTNUMDES DESCRIPTION
1-JUL-1996 AAABIKE 76 76 ROADBIKE
17-JAN-1996 BIKESPEC 76 76 ROADBIKE
19-MAY-1996 TRUEWHEEL 76 76 ROADBIKE
11-JUL-1996 JACKSBIKE 76 76 ROADBIKE
17-JAN-1996 LESHOPPE 76 76 ROADBIKE
顺着这个思路我们来看一下一个或多个表是如何进行联合的在下边的例子中
employee_id 显然是唯一标识列因为你可以有在同一个公司有相同薪水并且他们的名字
也相同的雇员但是他们会各自拥有他们自己的employee_id 所以如果要对这两个表进行
联合我们应该使用employee_id 列
EMPLOYEE_TABLE EMPLOYEE_PAY_TABLE
EMPLOYEE_ID EMPLOYEE_ID
LAST_NAME SALARY
FIRST _NAME DEPARTMENT
MIDDLE_NAME SUPERVISOR
MARITAL_STATUS
INPUT
SQL 21 日自学通(V1.0) 翻译人笨猪
128
SELECT E.EMPLOYEE_ID E.LAST_NAME EP.SALARY FROM EMPLOYEE_TBL E
EMPLOYEE_PAY_TBL EP WHERE E.EMPLOYEE_ID = EP.EMPLOYEE_ID
AND E.LAST_NAME = 'SMITH';
OUTPUT
E.EMPLOYEE_ID E.LAST_NAME EP.SALARY
13245 SMITH 35000.00
技巧如果你在联合表的时候没有使用WHERE 子句你执行的其实是笛卡尔联合也就
是笛卡尔叉积这种联合会对FROM 中指出的表进行完全的组合如果每个表有200
个记录的话那么所得到的结果将会有40000 行200 200 这太大了所以除非
你确实是想对表中的所有记录进行联合否则一定不要忘记使用WHERE 子句
现在回要原来的表中我们已经对联合进行了充分的准备可以用它来完成一些实际
的工作了找一下我们卖road bikes 共卖了多少钱
INPUT/OUTPUT
SELECT SUM O.QUANTITY * P.PRICE TOTAL FROM ORDERS O, PART P
WHERE O.PARTNUM = P.PARTNUM AND P.DESCRIPTION = 'ROAD BIKE'
TOTAL
19610.00
在这种设置中销售人员可以保证ORDERS 表的更新生产部门则可以保持PART 表
的更新而你则无需对数据库的底层进行重新设计
注注意在SQL 语句中表以及列的别名的使用你可能会因为别名多按了许多许多个按键
但是它可以让你的语句更具有可读性
我们可以对更多的表进行联合吗例如我们需要生成发票所要的信息可以这样写
INPUT/OUTPUT
SELECT C.NAME C.ADDRESS O.QUANTITY * P.PRICE TOTAL
FROM ORDER O PART P CUSTOMER C
WHERE O.PARTNUM = P.PARTNUM AND O.NAME = C.NAME
NAME ADDRESS TOTAL
TRUE WHEEL 55O HUSKER 1200.00
BIKE SPEC CPT SHRIVE 2400.00
SQL 21 日自学通(V1.0) 翻译人笨猪
129
LE SHOPPE HOMETOWN 3600.00
AAA BIKE 10 OLDTOWN 1200.00
TRUE WHEEL 55O HUSKER 2102.70
BIKE SPEC CPT SHRIVE 2803.60
TRUE WHEEL 55O HUSKER 196.00
AAA BIKE 10 OLDTOWN 213.50
BIKE SPEC CPT SHRIVE 542.50
TRUE WHEEL 55O HUSKER 1590.00
BIKE SPEC CPT SHRIVE 5830.00
JACKS BIKE 24 EGLIN 7420.00
LE SHOPPE HOMETOWN 2650.00
AAA BIKE 10 OLDTOWN 2120.00
把语句写成如下格式会更具有可读性
INPUT/OUTPUT
SELECT C.NAME C.ADDRESS O.QUANTITY * P.PRICE TOTAL
FROM ORDERS O PART P CUSTOMER C
WHERE O.PARTNUM = P.PARTNUM
AND O.NAME = C.NAME ORDER BY C.NAME
NAME ADDRESS TOTAL
AAA BIKE 10 OLDTOWN 213.50
AAA BIKE 10 OLDTOWN 2120.00
AAA BIKE 10 OLDTOWN 1200.00
BIKE SPEC CPT SHRIVE 542.50
BIKE SPEC CPT SHRIVE 2803.60
BIKE SPEC CPT SHRIVE 5830.00
BIKE SPEC CPT SHRIVE 2400.00
JACKS BIKE 24 EGLIN 7420.00
LE SHOPPE HOMETOWN 2650.00
LE SHOPPE HOMETOWN 3600.00
TRUE WHEEL 55O HUSKER 196.00
TRUE WHEEL 55O HUSKER 2102.70
TRUE WHEEL 55O HUSKER 1590.00
TRUE WHEEL 55O HUSKER 1200.00
注注意当将三个表进行联合的时候ORDERS PART CUSTOMER ORDERS 表
SQL 21 日自学通(V1.0) 翻译人笨猪
130
被使用了两次而其它的表只使用了一次通常根据给定的条件返回行数最少的表会作
为驱动表— — 也就是基表在查询中除基表以外的其它表通常是向基表联合以便更有效地
获得数据所以在本例中ORDERS 表是基表在大多数的数据库中只有很少的几个基表
直接或间接地与其它的所有表联合见第15 天高性能的SQL 语句流for more on
base tables.
在下边的使用中我们通过使用DESCRIPTION 列来使上述的查询更精确因而也就更
有效
INPUT/OUTPUT
SELECT C.NAME C.ADDRESS O.QUANTITY * P.PRICE TOTAL P.DESCRIPTION
FROM ORDERS O PART P CUSTOMER C
WHERE O.PARTNUM=P.PARTNUM AND O.NAME = C.NAME ORDER BY C.NAME
NAME ADDRESS TOTAL DESCRIPTION
AAA BIKE 10 OLDTOWN 213.50 TIRES
AAA BIKE 10 OLDTOWN 2120.00 ROAD BIKE
AAA BIKE 10 OLDTOWN 1200.00 TANDEM
BIKE SPEC CPT SHRIVE 542.50 PEDALS
BIKE SPEC CPT SHRIVE 2803.60 MOUNTAIN BIKE
BIKE SPEC CPT SHRIVE 5830.00 ROAD BIKE
BIKE SPEC CPT SHRIVE 2400.00 TANDEM
JACKS BIKE 24 EGLIN 7420.00 ROAD BIKE
LE SHOPPE HOMETOWN 2650.00 ROAD BIKE
LE SHOPPE HOMETOWN 3600.00 TANDEM
TRUE WHEEL 55O HUSKER 196.00 SEATS
TRUE WHEEL 55O HUSKER 2102.70 MOUNTAIN BIKE
TRUE WHEEL 55O HUSKER 1590.00 ROAD BIKE
TRUE WHEEL 55O HUSKER 1200.00 TANDEM
分析
这是三个表联合后的结果我们可以所得到的信息来开发票了
注在今天的开始SQL 曾经联合过TABEL1 和TABEL2 并生成了一个新表有X(TABLE1
的行数) Y(TABLE2 的行数)列联合并没有生成确实存在的表格但它生成了一个虚
拟的表格对两个表联合包括自我联合后会根据WHERE 所指定的条件生成一个
新的集合SELECT 语句减少了显示的列数但是WHERE 语句仍然把所有的列全返
回了在今天的例子中我们的表中只有为数不多的几列而现实生活中的数据可能会
SQL 21 日自学通(V1.0) 翻译人笨猪
131
有成千上万列如果你所使用的平台足够快那么多表联合可能对系统的性能没有影
响可是如果你工作在一个比较慢的平台上联合可能会导致死机