所以我是 Postgresl 的新手,我正在尝试熟悉嵌套查询及其工作原理,因为似乎有一些条件会增加直觉告诉我的内容。
我了解到,至少我认为我了解到,在 Postgresql 中,涉及子查询的
FROM
子句中需要别名。在尝试实施除法时,我发现了以下内容:
下面的查询有效,尽管我没有为从中选择的派生表添加别名:
SELECT *
FROM (
(SELECT state_id from state_drinks) AS state_ids
CROSS JOIN
(SELECT id FROM drinks) AS drink_ids
) -- NO ALIAS FOR OUTTER SELECT BUT WORKS;
但是,下面更复杂的查询(其中嵌套了上面的查询),需要别名:
SELECT state_id
FROM (
SELECT *
FROM (
(SELECT state_id from state_drinks) AS state_ids
CROSS JOIN
(SELECT id FROM drinks) AS drink_ids
) AS all_tuples
EXCEPT
SELECT *
FROM state_drinks AS actual_tuples
) AS eliminated_tuples --DOES NOT WORK ----WITHOUT 'As eliminated_tuples'
由于两个查询都涉及从派生表中进行选择,而派生表是通过执行涉及其他两个派生表和一个操作的子查询而获得的(第一个查询中为
CROSS JOIN
,第二个查询中为 EXCEPT
),为什么必须在第二个查询而不是第一个?
第一个查询的外括号不会生成派生表(您称之为子查询)。它只是指定连接嵌套顺序,在本例中这并不重要,因为您只有两个表。
例如,您可以有
SELECT *
FROM state_drinks AS si
LEFT JOIN (
drinks AS di
CROSS JOIN food f
) ON someConditionHere;
这意味着交叉连接的结果被左连接回
state_drinks
,而不是左连接的结果被交叉连接。
派生表具体定义为
这在 Postgres 16 中7.2.1.3。子查询
指定派生表的子查询必须括在括号中,并且必须分配表别名
FROM (SELECT * FROM table1) AS alias_name
7.2.1.3。子查询是单独定义的:7.2.1.1。连接表指定派生表的子查询必须括在括号中。
它们可能被分配了一个表别名...
...剪...FROM (SELECT * FROM table1) AS alias_name
根据 SQL 标准,必须为子查询提供表别名。
PostgreSQL 允许省略
AS
和别名,但在可能会移植到另一个系统的 SQL 代码中编写别名是一种很好的做法。但是连接周围的括号
...剪...
所有类型的联接都可以链接在一起或嵌套:
T1
和T2
中的一个或两个都可以是联接表。可以在子句周围使用括号来控制连接顺序。JOIN