问题:
最近我遇到了一个有趣的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 ...
我现在明白了为什么一个联接中的两个条件(通常是查询设计器提供的)会很有用,以及它会带来什么不同。
我想知道这是 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中试了一下,惊讶地发现它也不起作用。
我认为可能是由于缺少外键,所以我在我的查询中删除了所有表上的外键,但它仍然无法正常工作。
所以我的问题是:
为什么两个on条件是合法的,这有个名字吗?为什么它在我的第二个示例中不起作用?