3

问题:

我最近遇到了一个有趣的 SQL 问题。
我必须获得租赁对象的租赁合同。

问题是,每个房间可能有多个租赁合同,每个房间可能有多个租赁对象。

但是,由于糟糕的数据库修补,租赁合同被分配给房间,而不是租赁对象。因此,我不得不将合同编号与租赁对象编号进行比较,以获得正确的结果。

我以为这样可以:

SELECT * 
FROM T_Room 

LEFT JOIN T_MAP_Room_LeasingObject 
    ON MAP_RMLOBJ_RM_UID = T_Room.RM_UID 

LEFT JON T_LeasingObject
    ON LOBJ_UID = MAP_RMLOBJ_LOBJ_UID

LEFT JOIN T_MAP_Room_LeasingContract  
    ON T_MAP_Room_LeasingContract.MAP_RMCTR_RM_UID = T_Room.RM_UID 

LEFT JOIN T_Contracts 
    ON T_Contracts.CTR_UID = T_MAP_Room_LeasingContract.MAP_RMCTR_CTR_UID 
    AND T_Contracts.CTR_No LIKE ( ISNULL(T_LeasingObject.LOBJ_No, '') + '.%'     ) 

WHERE ...

但是,由于映射表在我获得合同号之前就已加入,并且没有映射表就无法获得合同号,因此我将条目翻了一番。

问题有点复杂,因为没有租赁合同的房间也需要出现,所以我不能只使用内部连接。

通过一些实验,我发现这可以按预期工作:

SELECT * 
FROM T_Room 

LEFT JOIN T_MAP_Room_LeasingObject 
    ON MAP_RMLOBJ_RM_UID = T_Room.RM_UID 

LEFT JON T_LeasingObject
    ON LOBJ_UID = MAP_RMLOBJ_LOBJ_UID

LEFT JOIN T_MAP_Room_LeasingContract  

LEFT JOIN T_Contracts 
    ON T_Contracts.CTR_UID = T_MAP_Room_LeasingContract.MAP_RMCTR_CTR_UID 
    ON T_MAP_Room_LeasingContract.MAP_RMCTR_RM_UID = T_Room.RM_UID 
    AND T_Contracts.CTR_No LIKE ( ISNULL(T_LeasingObject.LOBJ_No, '') + '.%'     ) 

WHERE ...

我现在明白了为什么一个连接中的两个 on 条件(通常由查询设计器提供)可能有用,以及它有什么不同。

我想知道这是否是 MS-SQL/T-SQL 特定的东西,或者这是否是标准 sql。

所以我在 PostgreSQL 中尝试了另外 3 个表。

所以我在其他 3 个表上写了这个查询:

SELECT * 
FROM t_dms_navigation

LEFT JOIN t_dms_document 
    ON NAV_DOC_UID = DOC_UID 

 LEFT JOIN t_dms_project 
    ON PJ_UID = NAV_PJ_UID 

并试图在条件下将其变成一个有两个

SELECT * 
FROM t_dms_navigation

LEFT JOIN t_dms_document 

 LEFT JOIN t_dms_project 
    ON PJ_UID = NAV_PJ_UID 
    ON NAV_DOC_UID = DOC_UID 

所以我认为它是 t-sql 特定的,但很快也在 MS-SQL 中尝试过,只是让我惊讶地发现它在那里也不起作用。

我认为这可能是因为缺少外键,所以我在房间查询中的所有表上删除了它们,但它仍然不起作用。

所以在这里我的问题
是:为什么 2 在条件下甚至是合法的,这有名字吗,为什么它在我的第二个例子中不起作用?

4

1 回答 1

5

这是标准的 SQL。每个JOIN都必须有一个相应的ON子句。你所做的只是改变连接发生在1中的顺序——这有点像改变表达式的括号来绕过优先规则。

A JOIN B ON <cond1> JOIN C ON <cond2>

首先加入AB基于cond1. 然后,它采用该组合行集并将其连接到C基于cond2.

A JOIN B JOIN C ON <cond1> ON <cond2>

首先加入BC基于cond1. 然后A,它将基于cond2.


它应该在 PostgreSQL 中工作 - 这是 SELECT 语句文档的相关部分:

其中from_item可以是以下之一:
[ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
with_query_name [ [ AS ] 别名 [ ( column_alias [, ...] ) ] ]
function_name ( [ argument [, ...] ] ) [ AS ] 别名 [ ( column_alias [, ...] | column_definition [, ...] ) ]
function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )
from_item [ NATURAL ] join_type from_item [ ON join_condition | 使用 (join_column [, ...] ) ]

这是相关的最后一行。请注意,这是一个递归定义 - 连接的左侧和右侧可以是任何东西 - 包括更多连接。


1与 SQL 一样,这是逻辑处理顺序 - 只要结果一致,系统就可以按照它认为最适合的顺序自由执行物理处理。

于 2013-09-24T08:23:04.867 回答