SQL Server - объединение OUTER и INNER объединений - PullRequest
14 голосов
/ 23 января 2009

У меня есть 3 таблицы, и я должен соединить внутреннюю таблицу A с таблицей B, но слева между таблицей A и таблицей C.

Могу ли я объединить внешнее и внутреннее объединение в одном запросе? Я могу вкладывать запросы и получать желаемый результат, но не могу выполнить оба объединения в одном запросе. Похоже, что в других языках SQL порядок соединения важен. Так ли это в SQL Server?


Хорошо, вот сценарий.

Рассмотрим 3 таблицы. Таблица A, Таблица F, Таблица D.

Мне нужно, чтобы набор записей содержал все строки в D независимо от того, существует ли он в F (после того, как он внутренне соединен с A). Итак, на ум приходит внешнее соединение. Что мне нужно, это:

  1. Сначала выполните внутреннее соединение между A и F, чтобы получить набор (это может быть нулевой набор)
  2. Затем выполните внешнее соединение с набором записей в (1) с помощью D

Ответы [ 9 ]

17 голосов
/ 23 января 2009

Если я правильно понимаю, вы хотите что-то вроде этого:

select
    *
from
    a 
    left outer join c
        inner join b on c.bID = b.ID
    on a.cID = c.ID
9 голосов
/ 15 марта 2012

В моем случае мне нужно было поместить псевдонимы таблиц, чтобы мой запрос работал правильно:

SELECT * FROM ("purchased_items" p1
     INNER JOIN "purchase_orders" po1 ON (po1."id" = p1."purchase_order_id")) AS p4
LEFT OUTER JOIN (purchased_items p2
      INNER JOIN "purchase_orders" po2 ON (po2."id" = p2."purchase_order_id")) AS p5
ON (p4.item_variant_id = p5.item_variant_id AND p4.delivery_date < p5.delivery_date) 
WHERE p5.delivery_date IS NULL AND p4.delivered <> 0 
4 голосов
/ 23 января 2009

Конечно, вы можете выполнить объединение в одном запросе: -

FROM TableA a
INNER JOIN Table b ON a.TableA_ID = b.TableA_ID
LEFT OUTER JOIN Table c ON a.TableA_ID = c.TableA_ID
2 голосов
/ 23 января 2009

Заказ не должен иметь значение.

Venn Diagram

Вот диаграмма Венна из Wikimedia Commons. Независимо от порядка запросов вы получите перекрытие между кругами A и B, с нулями для столбцов C, где C не перекрывает комбинацию A и B.

2 голосов
/ 23 января 2009

Вы можете использовать как внутренние, так и внешние объединения в одном запросе, но их порядок важен. Смотрите этот вопрос:
Внутреннее соединение и внешнее соединение; порядок таблиц важен?

1 голос
/ 23 января 2009

Из вашего наблюдения звучит так, как будто вы хотите «условное» внутреннее соединение.

По сути, «если A и B имеют запись, ВНУТРЕННЕЕ СОЕДИНЕНИЕ к C».

Однако вы, вероятно, столкнетесь с проблемой, когда INNER JOIN в вашем запросе не показывает записи, где A не имеет записей, связанных с B или C. Если они находятся в одной и той же «области видимости», INNERS всегда будет работать, их нельзя условно запускать в зависимости от их заказа.

Вы должны либо использовать два ЛЕВЫХ соединения и отфильтровать записи, которые вам не нужны, либо использовать View для выделения INNER JOIN.

Ex. ЛЕВОЕ СОЕДИНЕНИЕ vw_MyView ON A.ID = vw_MyView.A_ID

Где MyView имеет таблицы B и C с вашим INNER JOIN. Это позволит выполнить ВНУТРЕННЕЕ СОЕДИНЕНИЕ внутри представления, а затем вы сможете ВЕРНУТЬСЯ К РЕЗУЛЬТАТУ.

0 голосов
/ 09 марта 2018

Это приходит от 1 до нуля или многих, где у многих есть FK

Два подхода
приказ on
поставить outer присоединиться к последнему

К сожалению, вы изменили имена таблиц. Я буду использовать более поздние имена.

declare @TableD TABLE (PeopleID int primary key, Name varchar(10));
INSERT INTO @TableD VALUES
       (1, 'Chris')
     , (2, 'Cliff')
     , (3, 'Heather');

declare @TableA TABLE (ThingID int primary key, ThingName varchar(10))
INSERT INTO @TableA VALUES
       (14, 'Bike')
     , (17, 'Trailer')
     , (18, 'Boat');

declare @TableF TABLE (PeopleID int, ThingID int, primary key (PeopleID, ThingID));
INSERT INTO @TableF VALUES
       (1, 18)
     , (1, 17)
     , (2, 14);

SELECT D.Name, A.ThingName
FROM @TableD D 
LEFT JOIN @TableF F
     JOIN @TableA A 
       ON A.ThingID = F.ThingID 
  ON F.PeopleID = D.PeopleID
order by D.Name, A.ThingName;

SELECT D.Name, A.ThingName
FROM @TableF F 
JOIN @TableA A 
  ON A.ThingID = F.ThingID 
right join @TableD D
  ON D.PeopleID = F.PeopleID 
order by D.Name, A.ThingName;

Name       ThingName
---------- ----------
Chris      Boat
Chris      Trailer
Cliff      Bike
Heather    NULL
0 голосов
/ 23 января 2009

Возможно, проблема не в соединении (Энтони показал вам, как делать то, что вы нам описали). Помните, что у людей часто возникают проблемы с использованием левых объединений, потому что они пытаются вставить что-то в предложение where со ссылкой на таблицу справа сторона соединения, таким образом преобразуя его из внешнего соединения во внутреннее соединение (если только вы не ищите те записи, в которых второе поле таблицы имеет нулевое значение, что дает вам записи в первой таблице, а не во второй).

Мы могли бы помочь вам лучше, если бы мы сказали, что используемый вами код не содержит желаемых результатов, а также некоторые примеры данных и примеры результатов.

0 голосов
/ 23 января 2009

Да, вы можете выполнить оба запроса, и да, порядок важен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...