横向的派生的表
在定义派生的表的 FORM 子句中的任何查询都必须紧跟在 LATERAL 关键字之后,如果那个查询引用任何其他表或列,在同一 FROM 子句中该表或列出现得早于定义该派生的表的那个查询的话。
横向的派生的表,以及可在它们的语法中声明的表和列别名的引用的范围,是 SQL 语言的 ISO/ANSI 标准的一部分。此为 FROM 子句中横向的派生的表的语法:
LATERAL 派生的表
元素 描述 限制 语法
alias 在此为 subquery 结果的派生的表声明的临时名称 请参阅 AS 关键字。 标识符
column_alias 在此为派生的表中列声明的临时的名称 标识符
subquery 指定要检索的行 可为不相关的或相关的 SELECT 语句
用法
如果其结果集为派生的表的 subquery 引用任何早于在同一 FROM 子句中出现的任何表或列,则需要 LATERAL 关键字。此处,早于意味着在 FROM 子句中的从左至右的语法令牌顺序中“在派生的表的左边”。以 LATERAL 关键字定义的派生的表称为横向的派生的表。
这支持对 FROM 子句中的其他表中列的引用,而不是仅对随后的派生的表中列的引用。可提升在连接一个或多个派生的表的 SELECT 语句中的性能。在 DELETE、UPDATE 和 CREATE VIEW 语句之内的派生的表中,横向的表和列引用也是有效的。
如果在派生的表中,已解析了所有不相关的表和列引用,则在这些派生的表的 FROM 子句中不需要 LATERAL 关键字。
横向的派生的表的示例
下列查询在 FROM 子句中包括横向的派生的表,其中 t1_a 是横向的相关引用:
SELECT * FROM t1 ,
LATERAL (SELECT t2.a AS t2_a
FROM t2 WHERE t2.a = t1.a);
在下一示例中,d.deptno 是横向的相关引用:
SELECT d.deptno, d.deptname,
empinfo.avgsal, empinfo.empcount
FROM department d,
LATERAL (SELECT AVG(e.salary) AS avgsal,
COUNT(*) AS empcount
FROM employee e
WHERE e.workdept=d.deptno) AS empinfo;
在此,列表达式的 avgsal 和 empcount 别名以及 empinfo 横向的表引用出现在外查询的 projection 列表中,使用关联 deptno,从 department 表和派生的表连接符合条件的行。
对横向相关的引用的限制
下列限制适用于横向的关联的表和列引用:
不可在 ANSI FULL OUTER JOIN 查询中使用它们。
不可在 ANSI RIGHT OUTER JOIN 查询中使用它们。
不可在 GBase 8s 扩展 OUTER JOIN 查询中使用它们。
可用性和性能考虑
虽然通过视图、子查询可实现与表表达式等同的功能,但表表达式简化查询的公式,使得语法更加灵活和直观,并支持 SQL 的 ANSI/ISO 标准。
查询优化器不具体化 FROM 子句指定的简单的表表达式。与使用 GBase 8s 扩展 TABLE (MULTISET ( SELECT … )) 语法来在 FROM 子句中指定等同的派生的表的查询的性能比起来,在 FROM 子句中对表表达式使用 ANSI/ISO 语法的查询的性能至少一样好,设置如 UNION、INTERSECT 或 MINUS 操作符 这样的操作符,或将 ORDER BY 规范作为复合的表表达式实现,可造成比简单的表表达式更大的开销。请使用 SET EXPLAIN 语句来检测查询计划和表表达式的预计成本。
下列是有效的表表达式的示例:
SELECT * FROM (SELECT * FROM t);
SELECT * FROM (SELECT * FROM t) AS s;
SELECT * FROM (SELECT * FROM t) AS s WHERE t.a = s.b;
SELECT * FROM (SELECT * FROM t) AS s, (SELECT * FROM u) AS v WHERE s.a = v.b;
SELECT * FROM (SELECT SKIP 2 col1 FROM tab1 WHERE col1 > 50 ORDER BY col1 DESC);
SELECT * FROM (SELECT col1,col3 FROM tab1
WHERE col1 < 50 GROUP BY col1,col3 ORDER BY col3 ) vtab(vcol0,vcol1);
SELECT * FROM (SELECT * FROM t WHERE t.a = 1) AS s,
OUTER
(SELECT * FROM u WHERE u.b = 2 GROUP BY 1) AS v WHERE s.a = v.b;
SELECT * FROM (SELECT a AS colA FROM t WHERE t.a = 1) AS s,
OUTER
(SELECT b AS colB FROM u WHERE u.b = 2 GROUP BY 1) AS v
WHERE s.colA = v.colB;
CREATE VIEW vu AS SELECT * FROM (SELECT * FROM t);
SELECT * FROM ((SELECT * FROM t) AS r) AS s;
对连接和子查询中的外部表的限制
当您使用在连接和子查询中的外部表时,受到下列限制:
在查询中只有一个外部表是有效的。
该外部表不可为外连接中的外表。
对于不可转换成连接的子查询,您可使用在主查询中的外部表,但不可使用子查询中的。
您不可对外部表进行自连接。
要获取更多关于子查询的信息,请参阅您的 GBase 8s 性能指南 。