2013-09-24 2 views
3

Вопрос:SQL: Когда и почему разрешены два условия?

У меня недавно возникла интересная проблема 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 других таблиц:

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 на условиях даже законных, имеет ли это имя и почему он не работает на моем втором примере?

+1

«не работает» - вы получаете сообщения об ошибках? Они могут быть весьма информативными. –

+0

Сообщение об ошибке: Недопустимое имя объекта 't_dms_document'. Но имя правильно (правый каталог db также), если я выберу * из t_dms_document, я получаю результаты. –

ответ

5

Это стандартный SQL. Каждый JOIN должен иметь соответствующее предложение ON. Все, что вы делаете, это перемещение вокруг порядка, в котором происходит соединение, в - это немного похоже на изменение брекетинга выражения, чтобы обойти правила приоритета.

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

Сначала присоединяется A и B на основе cond1. Затем он берет этот объединенный набор строк и присоединяет его к C на основе cond2.

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

Сначала присоединяется B и C на основе cond1. Затем он принимает A и присоединяет его к предыдущему объединенному набору строк, основанному на cond2.


Он должен работать в PostgreSQL - вот соответствующая часть documentation в ЗЕЬЕСТ:

где from_item может быть один из:
[ONLY] table_name [*] [ [AS] alias [(column_alias [, ...])]]
(выберите) [AS] alias [(column_alias [, ...])]
с_query_name [[AS] alias [(column_alias [,. ..])]]
function_name ([argument [, ...]]) [AS] alias [(column_alias [, ...] | column_definition [, ...])]
имя_функции ([аргумент [, ...]]) AS (column_definition [, ...])
from_item [NATURAL] join_type from_item [ON join_condition | ИСПОЛЬЗОВАНИЕ (join_column [, ...])]

Это последняя строка. Обратите внимание, что это рекурсивное определение - то, что может быть слева и справа от соединения, может быть любым, в том числе большим количеством объединений.


Как всегда с SQL, это порядок обработки логический - система свободно выполнять физическую обработку в любой последовательности он чувствует будет работать лучше, если результат соответствует.

+0

А, я C. И что у меня в моем втором примере нет условия соединения для таблицы (b и c), только между (a и b) и (a и c), которые не могут работать, следовательно, ошибка, что правильно. –

Смежные вопросы