2014-12-22 5 views
4

У меня есть две таблицы:Sql LEFT OUTER JOIN с ИНЕКЕ

Запрос:

RequesID | Msg 
---------------- 
    5 | abc 
    6 | def 
    7 | ghi 
    8 | jkl 

RequestStatus:

RequestStatusID | RequestID |StatusID 
------------------------------------- 
     1    5   1 
     2    8   2 
  • Не каждый запрос имеет запись в RequestStatus

Мне нужны все данные из таблицы Request, за исключением случаев, когда StatusID = 2. (requestID=8 должен быть отфильтровывает)

Я использую LEFT OUTER JOIN, чтобы получать записи из таблицы Request но когда я добавляю Где пункт (Where StatusID = 1), конечно, это не работает.

ответ

9

Переместите ограничение на предложение on.

select * 
from request r 
left join requestStatus rs 
on r.requestID = rs.requestID 
--and status_id = 1 
and status_id <> 2 

Что происходит с вами, так это то, что сначала выполняется внешнее соединение. Любые строки, поступающие из внешнего соединения, которые не имеют совпадений, будут иметь нули во всех столбцах. Тогда применяется ваше предложение where, но с 1 <> null, это не сработает, как вы этого хотите.

РЕДАКТИРОВАТЬ: Изменено предложение, основанное на комментарии Пиюша.

+2

Я думаю, что OP хочет все строки, кроме тех случаев, когда statusID = 2, а не только 1 – HaveNoDisplayName

+0

Отличная точка, измененная позиция on. – Andrew

+0

Это не будет отфильтровывать строки, где 'StatusID = 2'. Удалите только правую сторону. –

1

Вы должны использовать NOT IN Query Statement как этот

Select * 
From Request 
Where RequestID not in 
    (Select RequestID 
    From RequestStatus 
    Where StatusID = 2) 

или

Select * 
From Request r 
left join requestStatus rs on r.requestID = rs.requestID 
Where r.RequestID not in 
    (Select RequestID 
    From RequestStatus 
    Where StatusID = 2) 
+0

Эндрю Ответ чище, чем моя – craigster

+0

Использования не существует статья быстрее, чем исключение , Not In, Outer Apply и т. Д. В этой статье [Aaron Bertrand - Должен ли я использовать NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT или NOT EXISTS?] (Http://sqlperformance.com/2012/12/t -sql-queries/left-anti-semi-join) – SqlZim

0

Ответ довольно прост, использовать левое соединение, но фильтр на строки, которые StatusID отличается от 2, например:

select * 
from request r 
left join requestStatus rs 
on r.requestID = rs.requestID 
where rs.StatusId <> 2 or rs.StatusId IS NULL 

EDIT: добавлено или rs.StatusId IS NULL дополнительное условие, которое также включает r ows в таблице requestStatus, которые не имеют соответствия в таблице запросов.

+0

Я ожидаю комментариев для downvote. –

+0

@Andrew: «Мне нужны все записи из таблицы Request, за исключением случаев, когда StatusID = 2. (requestID = 8 должен быть отфильтрован)» .. что еще нужно сказать? –

+0

Вот почему я удалил свой прощальный комментарий :) – Andrew

2

Попробуйте

SELECT * 
FROM Request R 
    LEFT JOIN RequestStatus RS ON R.RequestID = RS.RequestID 
    WHERE RS.StatusID <> 2 OR RS.RequestID IS NULL 

SQL FIDDLE

0

SqlFiddle

Этот ответ предполагает, что вы просто хотите RequestID & Msg из таблицы запроса, где нет записи в таблице RequestStatus с этим RequestID и StatusId от 2.

Вы не получите дополнительных записей для Запросы с несколькими записями RequestStatus с использованием этого запроса либо (vs Left join).

Использование не существует положения быстрее, чем исключение, не в том, Outer Нанести и т.д. в этой статье по Aaron Bertrand - Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?

select r.RequestId, r.Msg 
    from Request r 
    where not exists (
    select 1 
    from RequestStatus rs 
    where rs.StatusId = 2 
     and rs.RequestId = r.RequestId 
    )