Это довольно загруженный вопрос. Здесь недостаточно информации (например, план выполнения, количество записей, доступные индексы, физическое расположение данных в таблице и т. Д.), Чтобы правильно настроить запрос.Лучшее, что можно сделать, - это дать предположение.Это, как говорится ... вот мое лучшее предположение:
select distinct
tab_1.col_1,
tab_1.col_2 AS report,
tab_2.col_3 AS depot,
COUNT (DISTINCT (case when tab_3.col_8 = 'Parts Shortage' then tab_3.col_4 end)) over (partition by tab_1.col_1, tab_1.col_2) AS p_shortages,
COUNT (DISTINCT (case when tab_3.col_8 = 'Parts Shortage' then TRIM (tab_3.col_10) end)) over (partition by tab_1.col_1, tab_1.col_2) AS parts_affected,
COUNT (case when tab_3.col_8 = 'Parts Shortage' and tab_3.col_7 = 1 then tab_3.col_7 end) over (partition by tab_1.col_1, tab_1.col_2) AS parts_category1,
COUNT (case when tab_3.col_8 = 'Unsrv Asset' then tab_3.col_4 end) over (partition by tab_1.col_1, tab_1.col_2) AS u_shortages,
COUNT (case when tab_3.col_8 = 'Unsrv Asset' then tab_3.col_10 end) over (partition by tab_1.col_1, tab_1.col_2) AS u_affected,
COUNT (DISTINCT (case when tab_3.col_8 = 'Unsrv Asset' and tab_3.col_7 = 1 then TRIM(tab_3.col_7) end)) over (partition by tab_1.col_1, tab_1.col_2) AS unsrv_cat1,
TO_CHAR(tab_1.col_11, 'MM/DD/YY') AS report_date
from tab_1
left outer join tab_2
on tab_2.col_1 = tab_1.col_1
left outer join tab_3
on tab_3.col_9 = tab_1.col_1
AND tab_3.col_6 = tab_1.col_2
AND tab_3.col_5 IS NULL;
После более внимательного изучения запроса выше, чтобы объяснить, что я сделал, я изменил его дальше.Это было связано с тем, что я группировал по TO_CHAR (tab_1.col_11, «MM / DD / YY»), но увидел, что это не является частью коррелированных критериев подзапроса, поэтому его пришлось изменить (если только комбинация tab_1.col_1 и col_2сами по себе уникальны).
Итак, теперь попробуем объяснить это:
По сути, в исходном запросе происходит то, что для каждой строки tab_1 вы выполняете несколько запросов на tab_3.Поэтому вместо этого я изменил его на внешнее соединение на tab_3.Поскольку я не знаю данных, это должно было быть внешнее соединение, потому что коррелированный подзапрос не удалит строки из конечного вывода, где может быть внутреннее соединение.Я только что присоединился к tab_3 один раз, так как все подзапросы объединяли tab_3 обратно к tab_1, используя те же поля.Я просто переместил конкретную логику для каждого подзапроса в инструкцию case внутри счетчика, чтобы case возвращал ноль (и, следовательно, не считался), если критерии не были выполнены.Эта новейшая версия использует агрегатные функции для получения моих вычислений на правильном уровне (tab_1 col_1 и col_2, на которых основывался исходный подзапрос).Поскольку преобразование подзапроса во внешнее объединение могло создать больше строк (если между таблицами нет совпадения 1: 1), я добавил отличительные, чтобы получить только одну строку для каждой строки в tab_1.Все строки для каждой строки в tab_1 должны быть одинаковыми.Если в tab_1 уже есть дубликаты, вам нужно будет сделать что-то более глубокое, чтобы сохранить количество записей одинаковым.
Надеюсь, это имеет смысл.Если у вас есть вопросы, не стесняйтесь спрашивать, и я сделаю все возможное, чтобы объяснить дальше.
--------------------------- Более подробное объяснение
@ shawno: Вроде как, но я не думаю об этом, как о цикле. Используя ваш упрощенный пример, давайте представим, что ваши таблицы выглядят так:
TAB_1:
col_1 col_2
-------- ---------
A B
C D
TAB_3:
col_9 col_6 col_4
-------- --------- ---------
A B X
A B Y
A B Z
C D X
C D X
Используя метод подзапроса, вы просматриваете каждую строку tab_1 и затем выполняете запрос к tab_3.Таким образом, вы должны сделать:
для строки col_1 = A, col_2 = B, запустить счетчик выбора (отличный (col_4)) на tab_3, где col_9 = A и col_6 = B. Это возвращает значение 3, котороезначение, возвращаемое подзапросом.
для строки col_1 = C, col_2 = D, запустите счетчик выбора (отличный (col_4)) на tab_3, где col_9 = C и col_6 = D. Это возвращает значение 1, котороеэто значение, которое возвращает подзапрос.
Используя метод join, вы сначала объединяете таблицы, предоставляя вам такие данные, как:
col_1 col_2 col_9 col_6 col_4
-------- --------- -------- --------- ---------
A B A B X
A B A B Y
A B A B Z
C D C D X
C D C D X
Так что теперь вам просто нужно сделать запрос на основе этих данных., делая Count (отличный (col_4)) для каждого значения col_1, col_2.Если вы знаете, как выглядят ваши данные, вы можете создать более эффективный запрос, но идея остается той же.
Надеюсь, это сделает его немного более ясным!