2016-05-19 4 views
0

я вижу по разным вопросам на этом форуме об этом же теме, что консервы и часто появляется ответ:Охватывает ли Oracle подзапрос, вложенный на любой уровень?

Нет, Oracle не коррелируют подзапросы вложен более чем на один уровень (и ни один не делает MySQL).

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

ORA-00904: «CD» «FIELD6»:. Недопустимый идентификатор

Этот запрос важно быть вылеплены как это является и является лишь упрощенной версией фактического запроса, который включает оператор UNION. При отладке, почему сообщение об ошибке возвращалось, я уменьшил его до самой простой версии (ниже). Я понимаю, что могут быть альтернативные подходы JOIN к этой самой простой версии, но такие альтернативные подходы не будут отображаться для реального запроса. Если ниже может работать, то, похоже, наш более сложный запрос также может работать. Если нижеследующее не может работать, то что я неправильно читаю в документации Oracle и «консервированном» ответе выше?

SELECT a.* 
FROM 
    main_detail cd INNER JOIN 
    (
    SELECT 
     Field1, 
     Field2, 
     Field3, 
     Field4, 
     Field5, 
     Field6, 
     Field7 
    FROM other_detail x2 
    WHERE x2.Field1 = cd.Field1 AND x2.Field6 = cd.Field6 
    ) a ON 
    a.Field1 = cd.Field1 
    AND a.Field4 = cd.Field4 
    AND a.Field6 = cd.Field6 

Ниже приведено более похожее на нашу настоящую необходимость. UNION должно быть, как это должно позволить РЕГИСТРИРУЙТЕСЬ на множестве UNION-эд возвращенного, для которого используется в качестве РЕГИСТРИРУЙТЕСЬ внутрипартийной ограничить обратный набор записей:

SELECT h.*, a.* 
FROM 
    header h, 
    (
    SELECT 
     Field1, 
     Field2, 
     Field3, 
     Field4, 
     Field5, 
     Field6, 
     Field7 
    FROM main_detail x1 
    WHERE x1.Field1 = h.Field1 AND x1.Field6 = h.Field6 
    UNION 
    SELECT 
     Field1, 
     Field2, 
     Field3, 
     Field4, 
     Field5, 
     Field6, 
     Field7 
    FROM other_detail x2 
    WHERE x2.Field1 = h.Field1 AND x2.Field6 = h.Field6 
    ) a 
    WHERE 
     a.Field1 = h.Field1 AND 
     a.Field6 = h.Field6 

При сравнении выше не включая параметры коррелированного подзапроса и тестирование прогона в MS SQL, это улучшает производительность с 9 минут до 30-40 секунд, что является очень значительным улучшением. Я надеялся получить такую ​​же прибыль в Oracle.

Ниже так близко, как я могу сделать для реального кода, не ставя под угрозу конфиденциальность клиента:

SELECT DISTINCT 
    c.Field1, 
    c.Field2, 
    D.Field3, 
    b.Field4, 
    b.Field5, 
    c.Field6, 
    c.Field7 || '-' || cds1.Field8 AS status, 
    b.paid, 
    cds.Field8, 
    p.Field9, 
    p.Field10, 
    c.Field11, 
    c.Field12 AS provider_name 
FROM 
    header c, 
    (
    SELECT 
     a.*, 
     cd.paid, 
     cd.Field15, 
     cd.BigList, 
     cd.allowed, 
     cd.copayment, 
     cd.coinsurance 
    FROM 
     header_detail cd, 
     (
     SELECT 
      Field1, 
      Field4, 
      '' AS revenue_code, 
      Field20, 
      Field5, 
      Field14, 
      location_code, 
      ServiceList 
     FROM header_other_detail x1 
     WHERE x1.Field1 = cd.Field1 AND x1.Field14 = cd.Field14 
     UNION 
     SELECT 
      Field1, 
      Field4, 
      revenue_code, 
      Field20, 
      Field5, 
      Field14, 
      '' AS location_code, 
      ServiceList 
     FROM inst_claim_detail x2 
     WHERE x2.Field1 = cd.Field1 AND x2.Field14 = cd.Field14 
     ) a 
    WHERE 
     a.Field1 = cd.Field1 
     AND cd.Field1 = c.Field1 
     AND a.Field20 = cd.Field20 
     AND a.Field14 = cd.Field14 
     AND cd.Field14 = c.Field14a 
    ) b, 
    (
    SELECT 
     Field1, 
     Field14, 
     Trim(
      Trailing ',' FROM 
      ch.icd9_1 || ',' || 
      ch.icd9_2 || ',' || 
      ch.icd9_3 || ',' || 
      ch.icd9_4 || ',' || 
      ch.icd9_5 || ',' || 
      ch.icd9_6 || ',' || 
      ch.icd9_7 || ',' || 
      ch.icd9_8 || ',' || 
      ch.icd9_9 || ',' || 
      ch.icd9_10 || ',' || 
      ch.icd9_11 || ',' || 
      ch.icd9_12 
      ) 
     AS Field3 
    FROM prof_claim ch 
    WHERE ch.Field1 = c.Field1 AND ch.Field14 = c.Field14a 
    UNION 
    SELECT 
     Field1, 
     Field14, 
     Field3 
    FROM inst_claim x3 
    WHERE x3.Field1 = c.Field1 AND x3.Field14 = c.Field14a 
    ) d, 
    (
    SELECT 
     Field1, 
     Field14, 
     Field9, 
     Field10, 
     Field18, 
     refund_amount, 
     Field15 
    FROM payment_detail 
    ) p, 
    (SELECT * FROM Codes WHERE code_type='19') cds, 
    (SELECT * FROM Codes WHERE code_type='28') cds1 
WHERE 
    c.Field17 = 'T00000370' 
    AND c.Field1 = b.Field1 AND c.Field14a = b.Field14 
    AND c.Field1 = d.Field1 AND c.Field14a = d.Field14 
    AND b.Field14 = p.Field14(+) AND b.Field1 = p.Field1(+) AND b.Field15 = p.Field15(+) 
    AND b.BigList = cds.Field16(+) AND b.Field14 = cds.Field14(+) 
    AND c.Field7 = cds1.Field16(+) AND c.Field14a = cds1.Field14(+) 
ORDER BY Field1; 
+0

Oracle 12c поддерживает корреляцию более чем на один уровень. Все предыдущие версии только одного уровня. – Husqvik

ответ

1

В подзапроса

SELECT 
    Field1, 
    Field2, 
    Field3, 
    Field4, 
    Field5, 
    Field6, 
    Field7 
FROM other_detail x2 
WHERE x2.Field1 = cd.Field1 AND x2.Field6 = cd.Field6 

проверки где состояние. Если удалено полностью или, по крайней мере, удаление ссылки cd - запрос работает.

0

Если вы присоединяетесь к подзапросу таблицы (или другому подзапросу), то все условия соединения должны быть в условии ON, если вы используете соединения типа ANSI.

Причина, по которой ваш запрос терпит неудачу, заключается в том, что область подзапроса не распространяется за пределы себя. Он полностью отделен от области main_detail, поскольку вы пытаетесь присоединиться к таблицам, а не коррелировать их. Как предполагает ответ Marmite Bomber, подзапрос должен быть способен работать сам по себе, чего нет в вашей попытке.

Что вам нужно сделать, это переместить коррелированных фильтры к статье ON, например, так:

SELECT a.* 
FROM 
    main_detail cd INNER JOIN 
    (
    SELECT 
     Field1, 
     Field2, 
     Field3, 
     Field4, 
     Field5, 
     Field6, 
     Field7 
    FROM other_detail x2) a ON 
    a.Field1 = cd.Field1 
    AND a.Field4 = cd.Field4 
    AND a.Field6 = cd.Field6 
    and a.Field1 = cd.Field1 AND a.Field6 = cd.Field6 

, который, конечно же, идентичен:

SELECT a.* 
FROM 
    main_detail cd INNER JOIN 
    other_detail a ON 
     a.Field1 = cd.Field1 
     AND a.Field4 = cd.Field4 
     AND a.Field6 = cd.Field6 

Что касается к вашему запросу с UNION, это должно помочь вам получить некоторые преимущества по сравнению с исходным запросом:

SELECT * 
FROM (SELECT h1.*, 
       x1.field1, 
       x1.field2, 
       x1.field3, 
       x1.field4, 
       x1.field5, 
       x1.field6, 
       x1.field7 
     FROM main_detail x1 
       inner join header h1 on (x1.Field1 = h1.Field1 AND x1.Field6 = h1.Field6) 
     UNION 
     SELECT h2.* 
       field1, 
       field2, 
       field3, 
       field4, 
       field5, 
       field6, 
       field7 
     FROM other_detail x2 
       inner join header h2 on (x2.Field1 = h2.Field1 AND x2.Field6 = h2.Field6)); 
+0

Я обновил свой ответ альтернативным предложением. Из любопытства, сколько строк находится в ваших таблицах заголовков и подробностей? Кроме того, ожидаете ли вы вернуть те же данные из ваших основных и других таблиц подробностей? Потому что, если данные полностью разделены, вы можете использовать UNION ALL и сохранить себе операцию sort/different. – Boneist

+0

Приятный, но фактический запрос содержит 8 таблиц подвыборов и 5 основных таблиц, поэтому его просто невозможно выполнить с помощью просто подключений, не теряя целостности UNION, чтобы действовать как ограничивающий критерий против основной таблицы. Таким образом, UNION является одним из 4 других подобных UNIONS. Как указано в отредактированном сообщении выше, производительность изменяется с 9 минут до 30-40 секунд при тестировании в MS SQL. В Oracle примерно одинаковое время работы около 9 минут. Мы хотим получить то же преимущество, что и MS SQL. –

+0

Возможно, если вы можете обновить свой вопрос с помощью примерного запроса, который более точно отражает ваш фактический запрос, мы можем предложить вам улучшения, которые вы могли бы сделать. – Boneist