2016-11-11 2 views
1

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

SELECT bp.bp_id, 
    kd.kpi_def_id, 
    kd.kpi_name, 
    ks.kpi_status_now, 
    kd.threshold_min_val, 
    kd.threshold_max_val, 
    kd.threshold_min_alert, 
    kd.threshold_max_alert, 
    e.event_id, 
    e.event_name, 
    (SELECT * 
     FROM (SELECT l.log_desc 
      FROM rator_monitoring.alert_logs l 
      WHERE l.kpi_def_id = kd.kpi_def_id 
      ORDER BY TIMESTAMP DESC) 
     WHERE rownum = 1) log_desc 
FROM business_process bp 
JOIN kpi_definition kd 
ON  (kd.bp_id = bp.bp_id) 
JOIN rator_monitoring.kpi_status ks 
ON  (ks.kpi_def_id = kd.kpi_def_id) 
JOIN event e 
ON  (e.event_id = kd.event_id) 
WHERE kd.kpi_active_current = 'Y'; 

Что мне делать, чтобы исправить это?

+1

У вас есть подзапрос, который ссылается на таблицы из самого внешнего запроса. Увы, Oracle не позволяет ссылаться на таблицы более чем на один уровень. (Что отстой!) Какую версию Oracle вы используете? В Oracle 11 и выше лучший способ исправить это - с предложением WITH. – mathguy

+4

Плохая новость: вы не можете ссылаться на более чем 1 уровень вверх. (это по дизайну) Таким образом, ссылка на KD слишком удалена. нам пришлось бы реструктурировать запрос. либо CTE, либо переместить выделение на соединение как-то ... – xQbert

ответ

3

Вам необходимо преобразовать скалярный подзапрос log_desc, чтобы коррелированное соединение выполнялось на верхнем уровне. Например, что-то вроде:

SELECT ... 
     (SELECT max(l.log_desc) keep (dense_rank first order by l.timestamp desc) 
     FROM rator_monitoring.alert_logs l 
     WHERE l.kpi_def_id = kd.kpi_def_id) log_desc 
FROM ... 

N.B. тестировалась.

+0

Работает, но немного медленнее. Я предполагаю, что я допускаю поражение и разбиваю его на два запроса: – Adder

1

UNTESTED: реорганизован как соединение с использованием встроенных видов; не уверены в производительности, хотя ...

SELECT bp.bp_id, 
    kd.kpi_def_id, 
    kd.kpi_name, 
    ks.kpi_status_now, 
    kd.threshold_min_val, 
    kd.threshold_max_val, 
    kd.threshold_min_alert, 
    kd.threshold_max_alert, 
    e.event_id, 
    e.event_name, 
    l.log_desc 
FROM business_process bp 
JOIN kpi_definition kd 
    ON kd.bp_id = bp.bp_id 
JOIN rator_monitoring.kpi_status ks 
    ON ks.kpi_def_id = kd.kpi_def_id 
JOIN event e 
    ON e.event_id = kd.event_id 
LEFT JOIN (SELECT log_Desc 
     FROM rator_monitoring.alert_logs 
     INNER JOIN (SELECT max(timestamp) mts, kpi_def_ID 
        FROM rator_monitoring.alert_logs 
        GROUP BY kpi_def_ID) Z 
      ON Z.mts = l.timestamp 
     AND Z.kpi_def_ID = l.kpi_def_ID) l 
    ON l.kpi_def_id = kd.kpi_def_id 
WHERE kd.kpi_active_current = 'Y'; 
+0

Разве это не будет левое внешнее соединение из таблицы alert_logs обратно в таблицу kpi_definition? – Boneist

+2

Ах да. он должен, поскольку не может быть журнала Desc для каждой записи. и мы не хотим исключать данные – xQbert

+0

Обратите внимание, что если '(kp_def_id, timestamp)' tuple не гарантированно является уникальным, это может иметь встроенное представление 'l', чтобы иметь несколько строк с одинаковым значением' kpi_def_id'. Чтобы гарантировать, что на 'l' возвращается не более одной строки на' kp_def_id', нам понадобится 'GROUP BY kp_def_id' и совокупность вокруг' log_desc' ... 'MIN (log_desc)' или 'MAX (log_desc)' – spencer7593

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