【问题标题】:Oracle: invalid identifier in subselectOracle:子选择中的标识符无效
【发布时间】:2016-11-11 15:42:08
【问题描述】:

我正在尝试使用子选择从关联表中获取最后一行,但似乎子选择不知道外部查询中涉及的其中一个表,错误位于 kd.KPI_DEF_ID,无效标识符。将其替换为数字使查询有效。

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';

我能做些什么来解决这个问题?

【问题讨论】:

  • 您有一个从最外层查询引用表的子查询。唉,Oracle 不允许引用超过一级深度的表。 (太糟糕了!)您使用的是什么 Oracle 版本?在 Oracle 11 及更高版本中,解决此问题的最佳方法是使用 WITH 子句。
  • 坏消息是你不能引用超过 1 个级别。 (这是设计使然)所以对 KD 的引用太远了。我们必须重组查询。通过 CTE 或以某种方式将选择移动到连接...

标签: sql oracle subquery


【解决方案1】:

您需要转换 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   ...

注意未经测试。

【讨论】:

  • 工作,但有点慢。我想我会认输并将其分成两个查询,
【解决方案2】:

未测试:使用内联视图重组为连接;虽然不确定性能...

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';

【讨论】:

  • 不应该是从alert_logs表回kpi_definition表的左外连接吗?
  • 啊,是的。它应该是因为每条记录可能没有日志描述。而且我们不想消除数据
  • 请注意,如果不能保证 (kp_def_id,timestamp) 元组是唯一的,则内联视图 l 可能会有多行具有相同的 kpi_def_id 值。为了确保l 每个kp_def_id 最多返回一行,我们需要GROUP BY kp_def_idlog_desc 周围的聚合... MIN(log_desc)MAX(log_desc)
  • @spencer7593 的好点我确实做了这个假设。在我使用的大部分内容中,时间戳通常意味着它是独一无二的,但这并不一定是保证。
  • 我想要这个,但是在执行时我收到一个错误ORA-00904: "L"."KPI_DEF_ID": invalid identifier
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
相关资源
最近更新 更多