Ste*_*ger 3 sql t-sql sql-server postgresql join
题:
我最近有一个有趣的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 ...
Run Code Online (Sandbox Code Playgroud)
但是,因为映射表在我有合同号之前就加入了,并且我没有映射表就无法获得合同号,所以我有两倍的条目.
问题有点复杂,因为没有租赁合同的房间也需要出现,所以我不能只使用内部连接.
通过一些实验,我发现这可以按预期工作:
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 ...
Run Code Online (Sandbox Code Playgroud)
我现在明白为什么这两个条件在一个连接中,通常是查询设计者的礼貌,可能是有用的,它有什么不同.
我想知道这是否是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
Run Code Online (Sandbox Code Playgroud)
并尝试将其变为一个有两个条件
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
Run Code Online (Sandbox Code Playgroud)
所以我认为它是特定于t-sql的,但很快就在MS-SQL中尝试过,只是为了让我惊讶地发现它在那里也不起作用.
我认为可能是因为缺少外键,所以我在我的房间查询中的所有表上删除了它们,但它仍然无效.
所以我的问题是:
为什么2条件条件甚至是合法的,这是否有名称,为什么它不适用于我的第二个例子?
这是标准的SQL.每个人JOIN都必须有相应的ON条款.所有你正在做的就是改变连接发生在1的顺序- 这有点像改变表达式的包围以绕过优先规则.
A JOIN B ON <cond1> JOIN C ON <cond2>
Run Code Online (Sandbox Code Playgroud)
首先加入A并B基于cond1.然后它采用组合的行集并将其加入到C基于cond2.
A JOIN B JOIN C ON <cond1> ON <cond2>
Run Code Online (Sandbox Code Playgroud)
首先加入B并C基于cond1.然后A基于它将它连接到先前的组合行集cond2.
它应该在PostgreSQL中工作 - 这是SELECT语句文档的相关部分:
其中from_item可以是以下之一:
[仅] table_name [*] [[AS]别名[(column_alias [,...])]]
(选择)[AS]别名[(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一样,这是逻辑处理顺序 - 如果结果一致,系统可以按照感觉最好的顺序自由执行物理处理.