2013-06-05 3 views
0

У меня есть запрос, похожий на тот, который приведен ниже (хотя и более сложный). При запуске я получаю следующую ошибку: ORA-22818: Subquery expressions not allowed here в моей группе по заявлению.Подзапрос в группе по (ORACLE 9i)

Каков наилучший способ обойти эту проблему?

SELECT table1.ID 
     NVL(fget_office(fget_last_catc_id_by_date((SELECT MAX(table3.date) FROM table3 INNER JOIN table1 ON table1.ID = table3.id),table1.NUM), fget_max_split_line_no('FILL',(SELECT MAX table3.tc_id) FROM table3 INNER JOIN table1 ON table1.ID = table3.ID INNER JOIN table4 ON table3.tc_id = table3.tc_id))), table1.distribution) "OFFICE", --eper.DISTRIBUTION "OFFICE", 
     table1.name 
    FROM table1 
    LEFT JOIN table2 
    ON table1.ID = table2.ID 
WHERE table1.company in ('CP01', 'CP02') 
GROUP BY table1.ID, 
      NVL(fget_office(fget_last_catc_id_by_date((SELECT MAX(table3.date) FROM table3 INNER JOIN table1 ON table1.ID = table3.id),table1.NUM), fget_max_split_line_no('FILL',(SELECT MAX table3.tc_id) FROM table3 INNER JOIN table1 ON table1.ID = table3.ID INNER JOIN table4 ON table3.tc_id = table3.tc_id))), table1.distribution),   
      table1.name 

ответ

1

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

SELECT DISTINCT 
     table1.ID 
     NVL(fget_office(fget_last_catc_id_by_date((SELECT MAX(table3.date) FROM table3 INNER JOIN table1 ON table1.ID = table3.id),table1.NUM), fget_max_split_line_no('FILL',(SELECT MAX table3.tc_id) FROM table3 INNER JOIN table1 ON table1.ID = table3.ID INNER JOIN table4 ON table3.tc_id = table3.tc_id))), table1.distribution) "OFFICE", --eper.DISTRIBUTION "OFFICE", 
     table1.name 
    FROM table1 
    LEFT JOIN table2 
    ON table1.ID = table2.ID 
WHERE table1.company in ('CP01', 'CP02') 

В случае, если вы действительно делаете агрегацию в вашем «реальном» запросе, быстрый обходной путь будет использовать Common Table Expression (КТР), который поддерживается в Oracle 9i. В этом примере предполагается, что вы суммирование столбца с именем some_value:

WITH x AS (
    SELECT table1.ID 
     NVL(fget_office(fget_last_catc_id_by_date((SELECT MAX(table3.date) FROM table3 INNER JOIN table1 ON table1.ID = table3.id),table1.NUM), fget_max_split_line_no('FILL',(SELECT MAX table3.tc_id) FROM table3 INNER JOIN table1 ON table1.ID = table3.ID INNER JOIN table4 ON table3.tc_id = table3.tc_id))), table1.distribution) "OFFICE", --eper.DISTRIBUTION "OFFICE", 
     table1.name, 
     some_value 
    FROM table1 
    LEFT JOIN table2 
     ON table1.ID = table2.ID 
    WHERE table1.company in ('CP01', 'CP02') 
) 
SELECT ID, OFFICE, name, SUM(some_value) 
FROM x 
GROUP BY ID, Office, name 
1

Он смотрит на меня, как результаты этих функций прямо или косвенно определяются значениями table1.

Если это так, вы можете выполнить отдельную операцию по простому набору данных из таблицы1 и таблицы2 и применить функции после этого. Это уменьшит количество вызовов функций и повысит эффективность.

with cte1 as (
    select 
    table1.id 
    table1.num 
    table1.distribution, 
    table1.name 
    from 
    table1 left join table2 on (table1.id = table2.id) 
where 
    table1.company in ('CP01', 'CP02')) 
select 
    cte1.id, 
    coalesce(
    fget_office(
     fget_last_catc_id_by_date(
     (select max(table3.date) 
     from table3 inner join cte1 on cte1.id = table3.id), 
     cte1.num), 
     fget_max_split_line_no(
     'FILL', 
     (select max(table3.tc_id) 
     from table3 inner join cte1 on cte1.id  = table3.id 
         inner join table4 on table3.tc_id = table3.tc_id))), 
    table1.distribution) office 
    cte1.name 
from cte1 
/

Вы могли бы также привыкнуть к использованию Coalesce() вместо NVL() - это ANSI совместимый, более гибкий, и особенности оценки короткого замыкания, так что это удобно в вашем коде есть много PL/SQL-функции, вызываемые в SQL.

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