2015-09-16 1 views
0

Очень упрощенная настройка проблемы.объединить несколько запросов выбора в один, чтобы избежать множественного прохода над огромной таблицей

Таблица A содержит столбцы rz_id и sHashA. Таблица A очень большая.

Таблица B содержит столбцы scode и sHashB. Может быть много значений sHashB , соответствующих конкретному значению scode. Таблица B относительно велика меньше, чем таблица A.

Для каждого из значений scode (около 200 из них) я должен выполнить запрос, как показано ниже (в этом случае в этом случае scode равен 500).

select count(distinct rz_id) from A where substr(sHashA, 1, 5) in (select substr(sHashB, 1, 5) from B where scode = 500); 

Для каждого значения SCODE я пишу запрос, как выше, так что я в конечном итоге с 200 запросов, как так

select count(distinct rz_id) from A where substr(sHashA, 1, 5) in (select substr(sHashB, 1, 5) from B where scode = 500); 
select count(distinct rz_id) from A where substr(sHashA, 1, 5) in (select substr(sHashB, 1, 5) from B where scode = 501); 
select count(distinct rz_id) from A where substr(sHashA, 1, 5) in (select substr(sHashB, 1, 5) from B where scode = 502); 
. 
. 
. 
select count(distinct rz_id) from A where substr(sHashA, 1, 5) in (select substr(sHashB, 1, 5) from B where scode = 700); 

Проблема в том, что это в конечном итоге происходит за большим столом 200 раз , что отнимает много времени. Я хочу добиться этого с помощью одного прохода (один запрос).

Я подумал о сделать таблицу с таким количеством строк, как таблицы А и столько дополнительных столбцов как таблицы B с помощью запроса, как

select /*+ streamtable(a) */ a.*, if(substr(sHashA, 1, 5) in (select 
substr(sHashB, 1, 5) from B where scode = 500, 1, 0) as scode_500, 
if(substr(sHashA, 1, 5) in (select substr(sHashB, 1, 5) from B where 
scode = 501, 1, 0) as scode_501, ... if(substr(sHashA, 1, 5) in 
(select substr(sHashB, 1, 5) from B where scode = 700, 1, 0) as 
scode_700 from A a; 

Это было бы выход 0 или 1, в каждом из 200 столбцов соответствующий scode для строки таблицы A. Позже я смог подвести итоги столбцам, чтобы получить счет. Поскольку я также заинтересован в оценке перекрытия отсчетов между любыми двумя кодами, которые я думал о приведенной выше таблице.

Но я получаю ошибку синтаксического анализа, и я подозреваю, что запросы недопустимы внутри операторов IF.

Вопрос в конце концов заключается в следующем: как я могу свести все эти запросы к одному запросу, чтобы в итоге я столкнулся с строками огромной таблицы только один раз? Также представьте альтернативные способы обработки этого счета, учитывая, что я также заинтересован в перекрытии.

ответ

2

Что-то вроде этого;

select count(distinct A.rz_id), B.scode 
from A,B 
where substr(A.sHashA, 1, 5) = substr(B.sHashB, 1,5) 
and B.scode in (500,501,...) 
group by B.scode 

Однопроходные получает все данные, которые

+0

Спасибо. Не могли бы вы объяснить, как «substr (sHashA, ..) = substr (sHashB, ..)» будет работать, если для одного кода может быть несколько sHashB? Обмен «in» с «=» и устранение подзапроса select не ясен для меня. – awhan

+0

Это внутреннее соединение, которое имеет такой же эффект с вашим «in (subquery)». Присоединиться получает все матчи. Единый sHashB, несколько sHashB или без sHashB для данного кода не являются проблемами. Все покрыто. То, что вы сделали в своем запросе, заключалось в том, чтобы реализовать внутреннее соединение по-другому. –

+0

Единственное, что можно считать разницей в том, что: этот запрос не возвращает коды, которые не используются. Поэтому подсчет недостающих кодов равен нулю. –

Смежные вопросы