2013-05-23 3 views
1

У меня есть ситуация, когда я пытаюсь использовать коррелированный подзапрос, но я нахожусь в пределе вложенности в Oracle. Мне может быть недостает еще одной возможности, которую имеет Oracle, поэтому я подумал, что поставил бы этот вопрос здесь. Кто-нибудь знает, как переписать ниже SQL без использования этого предела вложенности, но также оставаться в пределах ниже ограничений?Есть ли обходной путь к ограничению вложенности подзапроса Oracle Correlated?

Ограничение:

  • Только SQL в предложении IN может быть изменено (Из-за ограничения, вне моего контроля)
  • Как показано, фильтрация в родительском запросе должна быть применена к подзапросы агрегации до агрегации.
  • Отфильтровать 0 на агрегацию colB после родительского фильтра применяется

Код ниже показывает мою попытку в этом перед запуском в пределе Oracle. Кроме того, версия Oracle, на которой я включен, - 11.2.0.2. Любая помощь будет оценена по достоинству. Благодаря!

SELECT 
    * 
FROM 
    table1 t1 
WHERE 
    t1.colA BETWEEN XXXX AND XXXX 
    AND t1.pk_id IN (
    SELECT 
     t2.pk_id 
    FROM (
     SELECT 
     t3.pk_id, 
     SUM(t3.amt) OVER (PARTITION BY t3.colB) amt 
     FROM table1 t3 
     WHERE t3.colA = t1.colA 
    ) t2 
    WHERE 
     t2.amt <> 0 
) 

Вот некоторые входные выборки/выходы, что я искал при работе над SQL:

Sample table1: 
----------------------------- 
| pk_id | colA | colB | amt | 
----------------------------- 
| 1 | 1 | A | 2 | 
| 2 | 1 | A | -1 | 
| 3 | 1 | B | 1 | 
| 4 | 2 | B | 1 | 
| 5 | 2 | A | -2 | 
| 6 | 2 | A | 1 | 
| 7 | 3 | A | 1 | 

Результаты SUM по t3.colB с t1.colA между 1 и 2:

--------------- 
| pk_id | amt | 
--------------- 
| 1 | 0 | 
| 2 | 0 | 
| 3 | 2 | 
| 4 | 2 | 
| 5 | 0 | 
| 6 | 0 |  

Результаты подзапроса для пункта IN с t1.colA между 1 и 2:

--------- 
| pk_id | 
--------- 
| 3 | 
| 4 | 

Результат запроса верхнего уровня с t1.colA между 1 и 2:

----------------------------- 
| pk_id | colA | colB | amt | 
----------------------------- 
| 3 | 1 | B | 1 | 
| 4 | 2 | B | 1 | 

После работы с некоторыми из ответов, полученных, у меня есть способ избежать вложенности предела в Oracle с простым заявлением СЛУЧАЯ:

SELECT 
    * 
FROM 
    table1 t1 
WHERE 
    t1.colA BETWEEN 1 AND 2 
    AND t1.pk_id IN (
    SELECT 
     CASE 
     WHEN SUM(t2.amt) OVER (PARTITION BY t2.colB) <> 0 THEN t2.pk_id 
     ELSE NULL 
     END 
    FROM table1 t2 
    WHERE t2.colA = t1.colA 
) 

К сожалению, это отразилось на реальной проблеме. Поскольку это подзапрос, я могу только перебирать одно значение диапазона t1.colA за раз. По-видимому, это делает невозможным выполнение аналитической суммы внутри этого диапазона в подзапросе. Поскольку я могу только модифицировать SQL внутри предложения IN, я не вижу решения этой проблемы. Если у кого-нибудь есть предложения, пожалуйста, дайте мне знать. Благодарю.

+0

Что на самом деле происходит при выполнении этого запроса? –

+0

Я получаю следующую ошибку: ORA-00904: «T1». Недопустимый идентификатор «COLA». – copo24

ответ

0

Если вы знаете, что между значениями являются и могут использовать те, в вашем подзапроса, то вы можете добавить, что к вашему подзапроса вместо:

SELECT 
    * 
FROM 
    table1 t1 
WHERE 
    t1.colA BETWEEN 1 AND 2 
    AND t1.pk_id IN (
     SELECT 
      t2.pk_id 
     FROM 
      (
       SELECT 
        t3.pk_id, 
        SUM(t3.amt) OVER (PARTITION BY t3.colB) amt 
       FROM table1 t3 
       WHERE t3.colA BETWEEN 1 AND 2 
      ) t2 
     WHERE 
      t2.amt <> 0 
    ) 

SQL Fiddle Demo

+0

Это часть сгенерированного оператора SQL, и, к сожалению, эти значения меняются в зависимости от других условий, поэтому я не могу полагаться на то, что они одинаковы. Все, что мне нужно, - это ввести мой SQL в предложение IN. Спасибо за ссылку SQL Fiddle, хотя я не знал об этом сайте - очень полезно. – copo24

0

Вы можете переписать запрос следующим образом:

SELECT * 
FROM table1 t1 
WHERE t1.colA BETWEEN XXXX AND XXXX and 
     t1.pk_id IN (
     SELECT t2.pk_id 
     FROM (SELECT t3.pk_id, t3.ColA, SUM(t3.amt) as amt 
       FROM table1 t3 
       group by t3.pk_id, t3.ColA 
       having sum(t3.amt) > 0 
      ) t2 
     WHERE t2.colA = t1.colA 
    ) 

Отсюда, вы можете записать его в виде:

select t1.* 
from table1 t1 join 
    (SELECT t3.pk_id, t3.ColA, SUM(t3.amt) as amt 
     FROM table1 t3 
     group by t3.pk_id, t3.ColA 
     having sum(t3.amt) > 0 
    ) t2 
    on t1.pk_id = t2.pk_id and t1.ColA = t3.ColA 
WHERE t1.colA BETWEEN XXXX AND XXXX 
+0

К сожалению, я не могу переписать весь запрос. В этой ситуации я могу изменить только сегмент внутри предложения IN. – copo24

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

  • Нет связанных вопросов^_^