Поиск пропущенного числа между таблицами в SQL

Я работаю над следующими двумя таблицами в Oracle 10g. Я пытаюсь выполнить довольно простую задачу, но не могу правильно ответить на свой запрос, возможно, из-за непонимания основ. Я хочу запросить account_no из TEMP, которого нет в BMF.

Две таблицы: Таблица 1: BMF: 1372 строки

account_no  |  trans_amount   | tracking_id

8149817     |   8100          |     72422912

8197743     |   9100          |     72422913

7165129     |   8100          |     72422914

8625861     |   8100          |     72422915

8463378     |   2100          |     72422916

8213330     |   3100          |     72422917

Таблица 2: temp: 1373 строки. В TEMP отсутствует только ОДИН аккаунт_номер, которого нет в BMF.

account_no

8149817

8197743

7165129

8625861

8463378

8213330

84633

48

Ожидаемый результат: 8463348 -- поскольку этот номер отсутствует в таблице BMF.

Мой запрос:

 select a1.account_no from TEMP a1, bmf a2 
 where a2.tracking_id between 72422912 and 72424283
 and a1.account_no != a2.account_no

Любые указатели с правильным запросом будут полезны

С уважением, новичок


person novice    schedule 11.09.2009    source источник


Ответы (4)


SELECT account_no FROM temp 
WHERE NOT EXISTS (SELECT account_no FROM bmf 
                  WHERE bmf.account_no = temp.account_no)


У него будет тот же план выполнения, что и у SQL в других ответах здесь, но он более четко излагает намерение (по крайней мере, для меня).

person zendar    schedule 11.09.2009

Вам нужны все значения столбца, которые находятся в одном наборе данных (temp), но не в другом (bmf)? Вот что такое "Минус" делает.

select account_no from TEMP
minus
select account_no from bmf

РЕДАКТИРОВАТЬ: добавлена ​​ссылка на документ

person Juergen Hartelt    schedule 12.09.2009

Пытаться

 select a1.account_no from TEMP a1 left join bmf a2 
 where a2.tracking_id between 72422912 and 72424283
 and a2.account_no = NULL

используйте левое соединение, а затем берите только те записи, у которых нет соответствующей записи

person Jonathan Fingland    schedule 11.09.2009

Ваш синтаксис присоединения не рекомендуется Oracle для внешних соединений.

Вы можете выполнить левое внешнее соединение и исключить несвязанные столбцы; это должно быть наиболее эффективным подходом. Что-то вроде этого:

SELECT a1.account_no FROM TEMP a1
 LEFT JOIN bmf a2 ON a1.account_no = a2.account_no
 WHERE (a2.tracking_id between 72422912 and 72424283)
 AND a2.account_no IS NULL
person Lucero    schedule 11.09.2009
comment
можете ли вы добавить ссылку на комментарий «разочарованный Oracle»? - person akf; 11.09.2009
comment
Я бы предпочел запрос NOT EXIST или NOT IN (OP явно запрашивает строки из TEMP, которых нет в BMF). Синтаксис с OUTER JOIN + NULL неудобен - person Vincent Malgrat; 11.09.2009
comment
@Vincent: привычка использовать NOT IN с дополнительным запросом может быстро привести к вложенному внутреннему запросу, что полностью снижает производительность. Поскольку мы говорим о SQL, мы должны иметь дело с множествами, а не с процедурными циклоподобными конструкциями... - person Lucero; 11.09.2009
comment
@Lucero: на самом деле NOT IN сгенерирует тот же план ANTI-JOIN, что и OUTER JOIN + NULL. Внутреннего запроса нет ни в растворе Светлозар, ни в зендаре (попробуйте). - person Vincent Malgrat; 11.09.2009
comment
@ Винсент: я знаю это. Вот почему я написал, что это может быстро привести к вложенному внутреннему запросу — когда кто-то использует столбцы из внешнего запроса более сложным образом. - person Lucero; 11.09.2009