本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
FROM 子句
查询中的 FROM 子句列出从中选择数据的表引用(表、视图和子查询)。如果列出多个表引用,则必须在 FROM 子句或 WHERE 子句中使用适当的语法来联接表。如果未指定联接条件,则系统将查询作为交叉联接(笛卡尔乘积)进行处理。
语法
FROM table_reference [, ...]
其中,table_reference 是下列项之一:
with_subquery_table_name | table_name | ( subquery ) [ [ AS ] alias ] table_reference [ NATURAL ] join_type table_reference [ USING ( join_column [, ...] ) ] table_reference [ INNER ] join_type table_reference ON expr
参数
- with_subquery_table_name
-
WITH 子句中的子查询定义的表。
- table_name
-
表或视图的名称。
- alias
-
表或视图的临时备用名称。必须为派生自子查询的表提供别名。在其他表引用中,别名是可选的。AS 关键字始终是可选的。表别名提供了用于标识查询的其他部分(例如 WHERE 子句)中的表的快捷方法。
例如:
select * from sales s, listing l where s.listid=l.listid
如果定义了表别名,则必须使用该别名在查询中引用该表。
例如,如果查询是
SELECT "tbl"."col" FROM "tbl" AS "t"
,则查询将失败,因为表名现在基本上已被覆盖。在这种情况下,有效的查询是SELECT "t"."col" FROM "tbl" AS "t"
。 - column_alias
-
表或视图中的列的临时备用名称。
- subquery
-
一个计算结果为表的查询表达式。表仅在查询的持续时间内存在,并且通常会向表提供一个名称或别名。但别名不是必需的。您也可以为派生自子查询的表定义列名称。如果您希望将子查询的结果联接到其他表并且希望在查询中的其他位置选择或约束这些列,则指定列的别名是非常重要的。
子查询可以包含 ORDER BY 子句,但在未指定 LIMIT 或 OFFSET 子句的情况下,该子句可能没有任何作用。
- NATURAL
-
定义一个联接,该联接自动将两个表中同名列的所有配对用作联接列。不需要显式联接条件。例如,如果 CATEGORY 和 EVENT 表都具有名为 CATID 的列,则这两个表的自然联接为基于其 CATID 列的联接。
注意
如果指定 NATURAL 联接,但表中没有要联接的同名列配对,则查询默认为交叉联接。
- join_type
-
指定下列类型的联接之一:
-
[INNER] JOIN
-
LEFT [OUTER] JOIN
-
RIGHT [OUTER] JOIN
-
FULL [OUTER] JOIN
-
CROSS JOIN
交叉联接是未限定的联接;它们返回两个表的笛卡尔乘积。
内部联接和外部联接是限定的联接。它们的限定方式包括:隐式(在自然联接中);在 FROM 语句中使用 ON 或 USING 语法;或者使用 WHERE 子句条件。
内部联接仅基于联接条件或联接列的列表返回匹配的行。外部联接返回与内部联接相同的所有行,还返回“左侧”表和/或“右侧”表中的非匹配行。左侧表是第一个列出的表,右侧表是第二个列出的表。非匹配行包含 NULL 值以填补输出列中的空白。
-
- ON join_condition
-
联接规范的类型,其中将联接列声明为紧跟 ON 关键字的条件。例如:
sales join listing on sales.listid=listing.listid and sales.eventid=listing.eventid
- USING ( join_column [, ...] )
-
联接规范的类型,其中用圆括号将列出的联接列括起来。如果指定多个联接列,则用逗号将它们分隔开。USING 关键字必须在列表之前。例如:
sales join listing using (listid,eventid)
使用说明
联接列必须具有可比较的数据类型。
NATURAL 或 USING 联接仅将每对联接列中的一个联接列保留在中间结果集中。
使用 ON 语法的联接会将两个联接列都保留在其中间结果集中。
另请参阅 WITH 子句。
JOIN 示例
SQL JOIN 子句用于根据公共字段合并两个或多个表中的数据。根据指定的联接方法,结果可能会发生变化,也可能不发生变化。有关 JOIN 子句的语法的更多信息,请参阅参数。
下面的查询是 LISTING 表和 SALES 表之间的内部联接(不带 JOIN 关键字),其中 LISTING 表中的 LISTID 介于 1 和 5 之间。此查询匹配 LISTING 表(左表)和 SALES 表(右表)中的 LISTID 列值。结果显示 LISTID 1、4 和 5 符合条件。
select listing.listid, sum(pricepaid) as price, sum(commission) as comm from listing, sales where listing.listid = sales.listid and listing.listid between 1 and 5 group by 1 order by 1; listid | price | comm -------+--------+-------- 1 | 728.00 | 109.20 4 | 76.00 | 11.40 5 | 525.00 | 78.75
以下查询是一个左外部联接。当在其他表中找不到匹配项时,左外部联接和右外部联接保留某个已联接表中的值。左表和右表是语法中列出的第一个表和第二个表。NULL 值用于填补结果集中的“空白”。此查询匹配 LISTING 表(左表)和 SALES 表(右表)中的 LISTID 列值。结果表明 LISTID 2 和 3 不会生成任何销售额。
select listing.listid, sum(pricepaid) as price, sum(commission) as comm from listing left outer join sales on sales.listid = listing.listid where listing.listid between 1 and 5 group by 1 order by 1; listid | price | comm -------+--------+-------- 1 | 728.00 | 109.20 2 | NULL | NULL 3 | NULL | NULL 4 | 76.00 | 11.40 5 | 525.00 | 78.75
以下查询是一个右外部联接。此查询匹配 LISTING 表(左表)和 SALES 表(右表)中的 LISTID 列值。结果显示 ListID 1、4 和 5 符合条件。
select listing.listid, sum(pricepaid) as price, sum(commission) as comm from listing right outer join sales on sales.listid = listing.listid where listing.listid between 1 and 5 group by 1 order by 1; listid | price | comm -------+--------+-------- 1 | 728.00 | 109.20 4 | 76.00 | 11.40 5 | 525.00 | 78.75
以下查询是一个完全联接。当在其他表中找不到匹配项时,完全联接保留已联接表中的值。左表和右表是语法中列出的第一个表和第二个表。NULL 值用于填补结果集中的“空白”。此查询匹配 LISTING 表(左表)和 SALES 表(右表)中的 LISTID 列值。结果表明 LISTID 2 和 3 不会生成任何销售额。
select listing.listid, sum(pricepaid) as price, sum(commission) as comm from listing full join sales on sales.listid = listing.listid where listing.listid between 1 and 5 group by 1 order by 1; listid | price | comm -------+--------+-------- 1 | 728.00 | 109.20 2 | NULL | NULL 3 | NULL | NULL 4 | 76.00 | 11.40 5 | 525.00 | 78.75
以下查询是一个完全联接。此查询匹配 LISTING 表(左表)和 SALES 表(右表)中的 LISTID 列值。结果中只有不会导致任何销售额的行(ListID 2 和 3)。
select listing.listid, sum(pricepaid) as price, sum(commission) as comm from listing full join sales on sales.listid = listing.listid where listing.listid between 1 and 5 and (listing.listid IS NULL or sales.listid IS NULL) group by 1 order by 1; listid | price | comm -------+--------+-------- 2 | NULL | NULL 3 | NULL | NULL
以下示例是与 ON 子句的内部联接。在这种情况下,不返回 NULL 行。
select listing.listid, sum(pricepaid) as price, sum(commission) as comm from sales join listing on sales.listid=listing.listid and sales.eventid=listing.eventid where listing.listid between 1 and 5 group by 1 order by 1; listid | price | comm -------+--------+-------- 1 | 728.00 | 109.20 4 | 76.00 | 11.40 5 | 525.00 | 78.75
以下查询是 LISTING 表和 SALES 表的交叉联接或笛卡尔联接,其中包含限制结果的谓词。此查询匹配 SALES 表和 LISTING 表中的 LISTID 列值,对应于这两个表中的 LISTID 1、2、3、4 和 5。结果显示 20 个行符合条件。
select sales.listid as sales_listid, listing.listid as listing_listid from sales cross join listing where sales.listid between 1 and 5 and listing.listid between 1 and 5 order by 1,2; sales_listid | listing_listid -------------+--------------- 1 | 1 1 | 2 1 | 3 1 | 4 1 | 5 4 | 1 4 | 2 4 | 3 4 | 4 4 | 5 5 | 1 5 | 1 5 | 2 5 | 2 5 | 3 5 | 3 5 | 4 5 | 4 5 | 5 5 | 5
以下示例是两个表之间的自然联接。在这种情况下,列 listid、sellerid、eventid 和 dateid 在两个表中具有相同的名称和数据类型,因此用作联接列。结果限制为 5 行。
select listid, sellerid, eventid, dateid, numtickets from listing natural join sales order by 1 limit 5; listid | sellerid | eventid | dateid | numtickets -------+-----------+---------+--------+----------- 113 | 29704 | 4699 | 2075 | 22 115 | 39115 | 3513 | 2062 | 14 116 | 43314 | 8675 | 1910 | 28 118 | 6079 | 1611 | 1862 | 9 163 | 24880 | 8253 | 1888 | 14
以下示例是使用 USING 子句在两个表之间进行的联接。在这种情况下,列 listid 和 eventid 用作联接列。结果限制为 5 行。
select listid, listing.sellerid, eventid, listing.dateid, numtickets from listing join sales using (listid, eventid) order by 1 limit 5; listid | sellerid | eventid | dateid | numtickets -------+----------+---------+--------+----------- 1 | 36861 | 7872 | 1850 | 10 4 | 8117 | 4337 | 1970 | 8 5 | 1616 | 8647 | 1963 | 4 5 | 1616 | 8647 | 1963 | 4 6 | 47402 | 8240 | 2053 | 18
以下查询是 FROM 子句中的两个子查询的内部联接。此查询查找不同类别的活动(音乐会和演出)的已售门票数和未售门票数:这些 FROM 子句子查询是表 子查询;它们可返回多个列和行。
select catgroup1, sold, unsold from (select catgroup, sum(qtysold) as sold from category c, event e, sales s where c.catid = e.catid and e.eventid = s.eventid group by catgroup) as a(catgroup1, sold) join (select catgroup, sum(numtickets)-sum(qtysold) as unsold from category c, event e, sales s, listing l where c.catid = e.catid and e.eventid = s.eventid and s.listid = l.listid group by catgroup) as b(catgroup2, unsold) on a.catgroup1 = b.catgroup2 order by 1; catgroup1 | sold | unsold ----------+--------+-------- Concerts | 195444 |1067199 Shows | 149905 | 817736