| 编写高级 SELECT 语句 / 创建高级连接 | |
连接不一定总是涉及两个不同的表,可以将表连接至它本身,创建自连接。当想要将列中的值与同一列中的其他值进行比较时,将表连接至它本身非常有用。
要创建自连接,在 FROM 子句中列出表两次,并且每次为它指定不同的别名。使用别名在 Projection 和 WHERE 子句中引用表。如同是两个独立的表一样。(SELECT 语句中的别名在别名和 GBase 8s SQL 指南:语法中讨论。)
与表之间的连接一样,可以在自连接中使用算术表达式,可以测试空值。可以使用 ORDER BY 子句来以升序或降序对指定列中的值进行排序。
图: 查询
SELECT x.order_num, x.ship_weight, x.ship_date,
y.order_num, y.ship_weight, y.ship_date
FROM orders x, orders y
WHERE x.ship_weight >= 5 * y.ship_weight
AND x.ship_date IS NOT NULL
AND y.ship_date IS NOT NULL
ORDER BY x.ship_date;
| order_num | ship_weight | ship_date | order_num | ship_weight | ship_date |
|---|---|---|---|---|---|
| 1004 | 95.80 | 05/30/1998 | 1011 | 10.40 | 07/03/1998 |
| 1004 | 95.80 | 05/30/1998 | 1020 | 14.00 | 07/16/1998 |
| 1004 | 95.80 | 05/30/1998 | 1022 | 15.00 | 07/30/1998 |
| 1007 | 125.90 | 06/05/1998 | 1015 | 20.60 | 07/16/1998 |
| 1007 | 125.90 | 06/05/1998 | 1020 | 14.00 | 07/16/1998 |
如果想要将自连接的结果存储到临时表中,那么将 INTO TEMP 子句追加到 SELECT 语句中,并至少对一组列指定显示标号,以重命名这些列。否则,重复列名将导致错误,并且不会创建临时表。
图: 查询
SELECT x.order_num orders1, x.po_num purch1,
x.ship_date ship1, y.order_num orders2,
y.po_num purch2, y.ship_date ship2
FROM orders x, orders y
WHERE x.ship_weight >= 5 * y.ship_weight
AND x.ship_date IS NOT NULL
AND y.ship_date IS NOT NULL
ORDER BY orders1, orders2
INTO TEMP shipping;
图: 查询结果
orders1 purch1 ship1 orders2 purch2 ship2
1004 8006 05/30/1998 1011 B77897 07/03/1998
1004 8006 05/30/1998 1020 W2286 07/16/1998
1004 8006 05/30/1998 1022 W9925 07/30/1998
1005 2865 06/09/1998 1011 B77897 07/03/1998
⋮
1019 Z55709 07/16/1998 1020 W2286 07/16/1998
1019 Z55709 07/16/1998 1022 W9925 07/30/1998
1023 KF2961 07/30/1998 1011 B77897 07/03/1998
可以多次将表连接至它本身。自连接的最大次数取决于您可用的资源。
图: 查询
SELECT s1.manu_code, s2.manu_code, s3.manu_code,
s1.stock_num, s1.description
FROM stock s1, stock s2, stock s3
WHERE s1.stock_num = s2.stock_num
AND s2.stock_num = s3.stock_num
AND s1.manu_code < s2.manu_code
AND s2.manu_code < s3.manu_code
ORDER BY stock_num;
图: 查询结果
manu_code manu_code manu_code stock_num description
HRO HSK SMT 1 baseball gloves
ANZ NRG SMT 5 tennis racquet
ANZ HRO HSK 110 helmet
ANZ HRO PRC 110 helmet
ANZ HRO SHM 110 helmet
ANZ HSK PRC 110 helmet
ANZ HSK SHM 110 helmet
ANZ PRC SHM 110 helmet
HRO HSK PRC 110 helmet
HRO HSK SHM 110 helmet
HRO PRC SHM 110 helmet
⋮
KAR NKL PRC 301 running shoes
KAR NKL SHM 301 running shoes
KAR PRC SHM 301 running shoes
NKL PRC SHM 301 running shoes
SELECT emp.employee_num, emp.gross_pay, emp.level,
emp.dept_num, mgr.employee_num, mgr.gross_pay,
mgr.dept_num, mgr.level
FROM payroll emp, payroll mgr
WHERE emp.gross_pay > mgr.gross_pay
AND emp.level < mgr.level
AND emp.dept_num = mgr.dept_num
ORDER BY 4;
图: 查询
SELECT order_num, total_price
FROM items a
WHERE 10 >
(SELECT COUNT (*)
FROM items b
WHERE b.total_price < a.total_price)
ORDER BY total_price;
图: 查询结果
order_num total_price
1018 $15.00
1013 $19.80
1003 $20.00
1005 $36.00
1006 $36.00
1013 $36.00
1010 $36.00
1013 $40.00
1022 $40.00
1023 $40.00
可以创建类似的查询来查找并列出公司中资格最老的 10 个职员。
有关相关子查询的更多信息,请参阅SELECT 语句中的子查询。