#sql-server #left-join
#sql-server #левое соединение
Вопрос:
У меня есть 2 таблицы ниже:
Table_1
[Group No] [Test No] [Description]
123 1 [First Test]
123 2 [Second Test]
123 3 [Third Test]
Table_2
[Sample No] [Test No] [Result Description]
ABC 1 [Some More Result]
ABC 3 [Some Result]
DEF 1 [A Result]
DEF 2 [Results More]
DEF 3 [Bad Results]
Вот мой запрос:
SELECT Table_1.[Group No], Table_1.[Test No], Table_1.Description, Table_2.[Result Description]
FROM Table_1
LEFT OUTER JOIN Table_2 ON Table_1.[Test No] = Table_2.[Test No]
WHERE (Table_1.[Group No] = '123') AND (Table_2.[Sample No] = 'ABC')
запрос Джакобсона:
SELECT Table_1.[Group No], Table_1.[Test No], Table_1.Description, Table_2.[Result Description]
FROM Table_1
LEFT OUTER JOIN Table_2 ON Table_1.[Test No] = Table_2.[Test No]
WHERE (Table_1.[Group No] = '123')
AND (Table_2.[Sample No] IS NULL OR Table_2.[Sample No] = 'ABC')
Это возвращает:
[Group No] [Test No] [Description] [Result Description]
123 1 [First Test] [Some More Result]
123 3 [Third Test] [Some Result]
Но чего я действительно хочу, так это:
[Group No] [Test No] [Description] [Result Description]
123 1 [First Test] [Some More Result]
123 2 [Second Test] NULL
123 3 [Third Test] [Some Result]
Возможно ли это? Я хотел бы вернуть запись с тестом № 2. Однако, как мне присоединиться к записи, которая не существует? Или это просто невозможно? Каковы альтернативы?
Ответ №1:
Несмотря на корректное использование внешнего соединения, вы ограничиваете результирующий набор случаями, когда значение присутствует в Table_2, включая столбец из этой таблицы в ваше предложение WHERE. Если вам нужны записи, в которых номер образца равен ABC, ИЛИ в Table_2 нет записи, вам нужно сделать это:
SELECT Table_1.[Group No], Table_1.[Test No], Table_1.Description, Table_2.[Result Description]
FROM Table_1
LEFT OUTER JOIN Table_2 ON Table_1.[Test No] = Table_2.[Test No]
WHERE (Table_1.[Group No] = '123')
AND (Table_2.[Sample No] IS NULL OR Table_2.[Sample No] = 'ABC')
В качестве альтернативы, вы можете отфильтровать результаты из Таблицы_2 при присоединении к ней (что в этом случае читается немного более чисто):
SELECT Table_1.[Group No], Table_1.[Test No], Table_1.Description, Table_2.[Result Description]
FROM Table_1
LEFT OUTER JOIN Table_2 ON Table_1.[Test No] = Table_2.[Test No] AND Table_2.[Sample No] = 'ABC'
WHERE (Table_1.[Group No] = '123')
Это должно выполнить то же самое. Важным выводом здесь является то, что предложение WHERE фильтрует результаты объединения ваших таблиц. Если вы используете внешние соединения, но хотите выполнить фильтрацию по таблицам с внешним соединением, вы должны обработать случай, когда на дальней стороне соединения не существует записи.
Комментарии:
1. Привет, Джакобсон, это по-прежнему дает те же результаты, я все еще не получаю строку с тестом № 2. Это как-то связано с ОБЪЕДИНЕНИЕМ?
2. Это странно… Какой именно запрос вы используете сейчас? Пожалуйста, отредактируйте свой вопрос, чтобы включить его (вы можете использовать форматирование исходного кода в вопросе, но не в комментарии).
3. Привет, Джакобсон, второй запрос, похоже, дал требуемые результаты. Я отредактировал свой первоначальный вопрос, включая первый запрос, который вы предложили — это не сработало, но второй сработал.
4. Ах, я протестировал это и понимаю, почему первый запрос исключает тест 2: поскольку он не фильтрует Table_2 при объединении, мы получаем запись для теста 2, присоединенную к образцу DEF. Затем мы фильтруем результаты для тех, которые не содержат выборки, или используем образец ABC, чтобы исключить запись для теста 2. (Самый простой способ увидеть, что происходит, — это выполнить SELECT * из соединенных таблиц без предложения WHERE). Итак, фильтрация Таблицы_2 при объединении, а затем фильтрация по группе после объединения — это правильный путь!
5. Спасибо, это ответ! Я должен помнить, что фильтрация в предложении WHERE ограничивает представление и что я должен делать это с помощью предложения FROM, правильно?