ЭКВИВАЛЕНТ ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ

У меня есть таблицы, содержащие нулевые значения. В таблице ORDER у меня есть 2 нулевых значения в разделе PART_ID и 2 нулевых значения в CUSTOMER_ID.

И у меня такой запрос:

SELECT O.ORDER_ID , O.ORDER_DATE , O.CUST_ID, O.QUANTITY ,O.PART_ID ,
       C.CUST_NAME, C.CUST_CODE, P.PART_NAME, P.PART_CODE
FROM [ORDER] O
     LEFT OUTER JOIN PART P ON P.PART_ID = O.PART_ID
     LEFT OUTER JOIN CUSTOMER C ON C.CUST_ID = O.CUST_ID 

Вот мой вопрос. Как я могу сделать это без использования внешнего соединения? Я пробовал слишком много вещей, в том числе там, где не существует или это;

SELECT *
FROM [ORDER] O ,CUSTOMER C, PART P
WHERE C.CUST_ID = (
  SELECT CUST_ID FROM CUSTOMER C WHERE O.CUST_ID = C.CUST_ID
) AND P.PART_ID = (SELECT PART_ID FROM PART P WHERE O.PART_ID = P.PART_ID) 

но я не мог найти решение. Если есть решение, то каким оно будет?

(Примечание: это домашнее задание.)

У меня есть такая таблица:

введите здесь описание изображения

и левое внешнее соединение дает следующее:

введите здесь описание изображения

hw сказал сделать это без использования внешнего соединения и получить ту же таблицу, что и левое внешнее соединение. Но, как сказал, я не мог. Я также использую MSSQL.


person developerCoder    schedule 22.03.2013    source источник
comment
Зачем тебе это?   -  person Yuck    schedule 22.03.2013
comment
Любопытно узнать почему, учитывая, что синтаксис устарел, а разочарован инструментами статического анализа   -  person Rowland Shaw    schedule 22.03.2013
comment
Также подразумевается OUTER в LEFT OUTER JOIN. Вместо этого вы можете просто написать LEFT JOIN.   -  person Yuck    schedule 22.03.2013
comment
Я думаю, что комментарий @Yuck - это ответ на ваш вопрос.   -  person hop    schedule 22.03.2013
comment
@MarkBannister - это политика SO, требующая объяснения, почему задан вопрос? Этот вопрос кажется мне довольно ясным, без дополнительной информации.   -  person topchef    schedule 22.03.2013
comment
@Yuck Я хочу сделать это, потому что мне так сказали. Они заставили меня обойтись без использования внешних соединений. Они сказали мне, что я могу сделать это с помощью простого выбора, внутреннего соединения и вложенного запроса. Я пытаюсь понять это, но я не мог.   -  person developerCoder    schedule 22.03.2013
comment
@developerCoder: Кто они такие и почему они рассказывают вам, как написать запрос? Это домашнее задание?   -  person    schedule 22.03.2013
comment
@MarkBAnnister Да, это домашняя работа, и я пытался выяснить это в течение 4 дней, но не смог.   -  person developerCoder    schedule 22.03.2013
comment
@developerCoder: ОК, отрицательный отзыв удален.   -  person    schedule 22.03.2013
comment
Да благословит вас Бог, какое глупое задание. Я никогда не пойму, почему преподаватели заставляют своих учеников выполнять работу (ИМХО) неправильным образом.   -  person Yuck    schedule 22.03.2013
comment
@Yuck Я думаю, что они заставляют нас думать по-другому, чтобы стать лучше.   -  person developerCoder    schedule 22.03.2013


Ответы (4)


Внешнее соединение создает надмножество над внутренним соединением. Действительно, из Википедии: Левое внешнее соединение возвращает все значения из внутреннего соединения плюс все значения в левой таблице, которые не соответствуют значениям в правой таблице.

Таким образом, для моделирования левого внешнего соединения с использованием внутреннего соединения можно использовать UNION внутреннего соединения SELECT между теми же таблицами с тем же условием соединения и другим SELECT из 1-го таблица, которая возвращает все строки без совпадения из правой таблицы (я сократил ваш случай до одного левого соединения):

SELECT O.ORDER_ID , O.ORDER_DATE , O.CUST_ID, O.QUANTITY ,O.PART_ID ,
       P.PART_NAME, P.PART_CODE
FROM [ORDER] O JOIN PART P ON P.PART_ID = O.PART_ID
UNION
SELECT O.ORDER_ID , O.ORDER_DATE , O.CUST_ID, O.QUANTITY ,O.PART_ID ,
       NULL, NULL 
FROM [ORDER] O
WHERE NOT EXISTS (SELECT 'found' FROM PART P WHERE P.PART_ID = O.PART_ID)
person topchef    schedule 22.03.2013
comment
@topchef Да, это правильно, но он не дал CUST_NAME и CUST_CODE, как я могу их добавить? - person developerCoder; 22.03.2013
comment
тогда это будет остальная часть вашей домашней работы: просто следуйте тому же подходу - удачи! - person topchef; 22.03.2013

Предположительно, вы хотите получить совпадения со столбцами со значениями NULL, а не с ошибкой. Если это так, просто измените условия соединения:

FROM [ORDER] O
     LEFT OUTER JOIN PART P
     ON P.PART_ID = O.PART_ID or (p.Part_id is NULL and o.Part_id is null)
     LEFT OUTER JOIN CUSTOMER C
     ON C.CUST_ID = O.CUST_ID or (c.cust_id is null and o.cust_id is null)

Основная проблема с этим подходом заключается в том, что многие (большинство?) SQL-движков не будут использовать индексы для соединения.

person Gordon Linoff    schedule 22.03.2013

Есть ли конкретная причина, по которой вы не хотите использовать внешнее соединение? Разве это не тот результат, который вы хотите? :

FROM [ORDER] O 
LEFT JOIN PART P 
ON P.PART_ID = O.PART_ID and P.PARTID is not null
LEFT JOIN CUSTOMER C 
ON C.CUST_ID = O.CUST_ID and C.CUSTID is not null
person Thanos Darkadakis    schedule 22.03.2013

Итак, полный ответ должен быть таким (после того, как мой учитель дал результаты):

 SELECT O.ORDER_ID,O.ORDER_DATE,O.CUST_ID,
(SELECT C.CUST_CODE FROM CUSTOMER C WHERE C.CUST_ID=O.CUST_ID) AS CUST_CODE,
(SELECT C.CUST_NAME FROM CUSTOMER C WHERE C.CUST_ID=O.CUST_ID) AS CUST_NAME,
O.PART_ID,
(SELECT P.PART_CODE FROM PART P WHERE P.PART_ID = O.PART_ID ) AS PART_CODE,
(SELECT P.PART_NAME FROM PART P WHERE P.PART_ID = O.PART_ID ) AS PART_NAME,
O.QUANTITY

FROM [ORDER] O
person developerCoder    schedule 31.03.2013