为什么SQL/PostgreSQL允许在联接子句中不引用联接表中的列的情况下进行联接



考虑以下情况:

create table contract(contract_id bigint, client_id bigint, second_client_id bigint);
insert into contract
values(10, 1, 3),
(11, 2, 4),
(12, 3, 6)
;
create table client(client_id bigint, user_name varchar);
insert into client
values(1, 'A'),
(2, 'B'),
(3, 'C'),
(4, 'D'),
(5, 'E'),
(6, 'F')
;

我看不到以下查询风格的用例,但Postgres(我测试过它(和其他SQL RDMS服务允许查询而不会抛出错误/警告:

select * 
from contract c
left join client ct1 on ct1.client_id = c.client_id
left join client ct2 on ct1.client_id = c.second_client_id

请注意,第二个联接不引用正在联接的表中的列(即第二个client联接别名为ct2,但联接子句中没有ct2列(。我不明白为什么人们会想要这样的结果,但没有任何警告或错误。在大型表中,尝试这种联接并返回null可能会浪费大量时间,只有这样,编写查询的人才会意识到自己的错误。

很好奇这种类型查询的任何用例,如果没有,为什么还没有建立错误处理。

编辑:正如评论中所指出的,联接在语法上是正确的,因此不会引发错误——查询规划器在执行之前不会检查联接功能。

由于联接条件是一个布尔表达式,它只引用FROM子句中以前表中的列,因此它没有任何问题。SQL中没有任何内容禁止您以这种方式编写交叉联接,而且编写类似的内容也并不罕见

FROM tab
LEFT JOIN LATERAL unnest(tab.arr)
ON TRUE

因此,除了违反SQL标准之外,禁止这样做似乎是不可能的。

你的愿望并不罕见,这是众所周知的代码";按照我的意思去做";(DWIM(。就我个人而言,我讨厌那些认为他们比我更清楚我想要什么的系统,并用他们有用的警告来困扰我。

您必须理解的一件重要事情是,联接不仅是比较两个表中的值的谓词,而且是任何数量的表的谓词。

这种情况在RDBMS llitterature中被称为";三角形连接";,涉及3张或更多的桌子。。。

在您的查询中,三角形连接是真实的,也可以写成:

select * 
from contract c
left join client ct1 on ct1.client_id = c.client_id
left join client ct1 on ct1.client_id = c.second_client_id
CROSS JOIN ct2

相关内容

  • 没有找到相关文章