考虑以下情况:
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