質問:
最近、興味深い 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 ...
ただし、契約番号を取得する前にマッピング テーブルが結合され、マッピング テーブルがないと契約番号を取得できないため、エントリが 2 倍になりました。
問題はもう少し複雑で、リース契約のない部屋も表示する必要があるため、内部結合だけを使用することはできませんでした。
少し実験したところ、これが期待どおりに機能することがわかりました。
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 ...
これで、1 つの結合で 2 つの on 条件 (通常はクエリ デザイナーの好意による) が役立つ理由と、それがもたらす違いがわかりました。
これは MS-SQL/T-SQL 固有のものなのか、それとも標準 SQL なのか疑問に思っていました。
そこで、別の 3 つのテーブルを使用して PostgreSQL で試しました。
そこで、他の 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
条件付きで2つで1つに変えようとしました
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 条件付きでも合法なのか、これには名前があるのか、2 番目の例ではなぜ機能しないのか?