2009-04-16 3 views
5

У меня есть таблица, назовем ее «a», которая используется в левом соединении в представлении, которое включает в себя множество таблиц. Тем не менее, я хочу только вернуть строки «a», если они также присоединяются к другой таблице «b». Таким образом, существующий код выглядитОграничение LEFT JOIN

SELECT .... 
FROM main ... 
... 
LEFT JOIN a ON (main.col2 = a.col2) 

, но он возвращает слишком много строк, конкретно те, где не имеют аналогов в б. Я попытался

SELECT ... 
FROM main ... 
... 
LEFT JOIN (
    SELECT a.col1, a.col2 
    FROM a 
    JOIN b ON (a.col3 = b.col3)) ON (a.col2 = main.col2) 

, который дает мне правильные результаты, но, к сожалению, «EXPLAIN PLAN» говорит, что делает это таким образом в конечном итоге вынудив полный просмотр таблицы А и Б, который делает вещи довольно медленно. Один из моих сотрудников предложил другую LEFT JOIN на b, но это не работает, потому что она дает мне строку b, когда она присутствует, но не перестает возвращать строки из числа, которые не имеют соответствия в b.

Есть ли способ поместить условие main.col2 в sub-SELECT, которое избавится от полного сканирования таблицы? Или какой-то другой способ сделать то, что я хочу?

ответ

6
SELECT ... 
FROM .... 
LEFT JOIN (a INNER JOIN b ON ....) ON .... 
+0

По какой-то нечетной причине левое соединение теперь действует как нормальное соединение. –

+0

+1 Это именно то, что я собирался предложить. –

+0

Хорошо, не обращая внимания на то, что я сказал раньше, - я это исправил. –

3
  1. добавить где (main.col2 = a.col2)

  2. просто объединение вместо левого присоединиться.

+0

Мне нужно сделать LEFT JOIN, потому что мне нужно вернуть строки в главном, которые не имеют соответствия в. –

+0

Несомненно, но не можете ли вы присоединиться к объединению (main, a) и b в качестве не-левого соединения? – tpdi

+0

Существует не строка из b для каждой строки основного. Выполнение без левого соединения оставило бы большинство основных, не так ли? –

0

Что делать, если вы создали представление, которое позволяет вам присоединиться к «a», чтобы «b» присоединиться, а затем ваши левые соединения к этому представлению?

0
Select ... 
    From Main 
    Left Join a on main.col2 = a.col2 
    where a.col3 in (select b.col3 from b) or a.col3 is null 

вам может понадобиться сделать некоторые индексацию a.col3 и b.col3

0

Сначала определите запрос между столом «а» и «б», чтобы убедиться, что он возвращается строки, которые вы хотите :

Select 
    a.field1, 
    a.field2, 
    b.field3 
from 
    table_a a 

    JOIN table_b b 
     on (b.someid = a.someid) 

затем положить, что в качестве подзапроса вашего основного запроса:

select 
    m.field1, 
    m.field2, 
    m.field3, 
    a.field1 as a_field1, 
    b.field1 as b_field1 
from 
    Table_main m 

    LEFT OUTER JOIN 
     (
     Select 
     a.field1, 
     a.field2, 
     b.field3 
     from 
     table_a a 

     JOIN table_b b 
      on (b.someid = a.someid) 
    ) sq 
    on (sq.field1 = m.field1) 

, который должен сделать это.

Ahh, пропустил заметку о проблемах с производительностью - то, что я обычно делаю, заключается в том, чтобы поместить запрос из представления в хранимую процедуру, чтобы я мог генерировать подзапросы для временных таблиц и накладывать на них индексы. Удивительно быстрее, чем вы ожидали. :-)

+0

Он уже сделал это, но есть проблема с производительностью. –

+0

Это похоже на то, что я описал в вопросе. –

+0

Да, я читал это слишком быстро. :-) –