【问题标题】:Oracle Query ORA-01799: a column may not be outer-joined to a subqueryOracle 查询 ORA-01799:列不能外连接到子查询
【发布时间】:2016-12-17 00:35:40
【问题描述】:

我编写了一个运行了数周的查询,但今天早上我的 Select Inner Join 出现以下错误

ORA-01799:列不能外连接到子查询

这是我的查询

SELECT 
     PERSON.PERSONID, 
     PERSON.LASTNAME, 
     PERSON.FIRSTNAME, 
     PERSON.MIDDLENAME,


FROM PERSON_VIEW PERSON
LEFT JOIN (SELECT PERSONID, DRIVERLICENSE_NUM, DRIVERLICENSE_EXP_DT,UPDATED_DT  
                        FROM DRIVERLICENSE_VIEW) DRIVERLICENSE
ON DRIVERLICENSE.PERSONID = PERSON.PERSONID AND 
       ((trunc(sysdate) - DRIVERLICENSE.UPDATED_DT <= 1000)) AND
       DRIVERLICENSE_EXP_DT = (SELECT MAX(DRIVERLICENSE_EXP_DT)   
                               FROM DRIVERLICENSE_VIEW PPT
                               WHERE PPT.PERSONID = DRIVERLICENSE_VIEW.PERSONID)

当我删除内部查询时,它可以工作,但这工作了几个星期。

DRIVERLICENSE_EXP_DT = (SELECT MAX(DRIVERLICENSE_EXP_DT)   
                        FROM DRIVERLICENSE_VIEW PPT
                        WHERE PPT.PERSONID = DRIVERLICENSE_VIEW.PERSONID)

如何修复此查询以使其再次工作?

谢谢。

【问题讨论】:

  • 您确定该查询早先有效吗,因为我确信它永远不会运行,因为它有错误。检查您发布的查询的第 5 行。
  • 这里通常的做法是将子查询作为视图持久化,然后加入该视图。
  • 正如@Raj_Te 所指出的,查询只是突然 开始产生此错误是不可能的。如果它以前工作过,那么它一定是一个不同的查询。
  • 您确定您(或某人/某事)没有更改该子查询吗? WHERE 子句有什么作用?您在 LHS 上有 PPT,在 RHS 上有 DRIVERLICENSE_VIEW,但是在上面的行中,您将 PPT 定义为 DRIVERLICENSE_VIEW 的另一个名称...您只是在 personid 中测试非空值吗?因为这就是 WHERE 子句的全部作用。或者这是您实际查询的修改版本?

标签: sql oracle


【解决方案1】:

您可以使用解析row_number() 函数来识别具有最新到期日期的记录。因此,将以下表达式添加到内部选择列表中:

ROW_NUMBER() OVER (PARTITION BY PERSONID ORDER BY DRIVERLICENSE_EXP_DT DESC) AS RN

...然后将结果过滤到RN = 1而不是子查询检查:

SELECT    PERSON.PERSONID, 
          PERSON.LASTNAME, 
          PERSON.FIRSTNAME, 
          PERSON.MIDDLENAME,
          DRIVERLICENSE.DRIVERLICENSE_NUM, 
          DRIVERLICENSE.DRIVERLICENSE_EXP_DT,
          DRIVERLICENSE.UPDATED_DT
FROM      PERSON_VIEW PERSON
LEFT JOIN (SELECT PERSONID, 
                  DRIVERLICENSE_NUM, 
                  DRIVERLICENSE_EXP_DT,
                  UPDATED_DT,
                  ROW_NUMBER() OVER (PARTITION BY PERSONID 
                                     ORDER BY DRIVERLICENSE_EXP_DT DESC) AS RN
           FROM   DRIVERLICENSE_VIEW) DRIVERLICENSE
        ON DRIVERLICENSE.PERSONID = PERSON.PERSONID
       AND trunc(sysdate) - DRIVERLICENSE.UPDATED_DT <= 1000
       AND RN = 1

如果您将sysdate 测试移到子查询中,我还希望您可以获得更多可能感兴趣的非空驾驶执照结果——但这完全取决于您想要实现的目标:

SELECT    PERSON.PERSONID, 
          PERSON.LASTNAME, 
          PERSON.FIRSTNAME, 
          PERSON.MIDDLENAME,
          DRIVERLICENSE.DRIVERLICENSE_NUM, 
          DRIVERLICENSE.DRIVERLICENSE_EXP_DT,
          DRIVERLICENSE.UPDATED_DT
FROM      PERSON_VIEW PERSON
LEFT JOIN (SELECT PERSONID, 
                  DRIVERLICENSE_NUM, 
                  DRIVERLICENSE_EXP_DT,
                  UPDATED_DT,
                  ROW_NUMBER() OVER (PARTITION BY PERSONID 
                                     ORDER BY DRIVERLICENSE_EXP_DT DESC) AS RN
           FROM   DRIVERLICENSE_VIEW
           WHERE  trunc(sysdate) - UPDATED_DT <= 1000) DRIVERLICENSE
        ON DRIVERLICENSE.PERSONID = PERSON.PERSONID
       AND RN = 1

最后,我想你也在你的主select中从driverlicense中选择一些字段,否则执行left join几乎没有用处。

【讨论】:

    【解决方案2】:
    SELECT   
     PERSON.PERSONID,   
     PERSON.LASTNAME,  
     PERSON.FIRSTNAME,  
     PERSON.MIDDLENAME  
    FROM PERSON_VIEW PERSON  
    LEFT JOIN (SELECT PERSONID,  
        DRIVERLICENSE_NUM,  
        DRIVERLICENSE_EXP_DT,  
        UPDATED_DT    
        FROM DRIVERLICENSE_VIEW) DRIVERLICENSE  
    ON DRIVERLICENSE.PERSONID = PERSON.PERSONID  
        AND ((trunc(SYSDATE) - DRIVERLICENSE.UPDATED_DT <= 1000))  
        AND DRIVERLICENSE_EXP_DT = (SELECT MAX(DRIVERLICENSE_EXP_DT)   
                                FROM   DRIVERLICENSE_VIEW PPT  
                                WHERE PPT.PERSONID = DRIVERLICENSE.PERSONID)
    

    最后一行出现错误,因为查询中没有任何对象 DRIVERLICENSE_VIEW,您的别名为 DRIVERLICENSE。我希望这会奏效。

    您可以在左连接中直接使用表而不是子查询,因为它的工作方式相同:

    SELECT 
     PERSON.PERSONID, 
     PERSON.LASTNAME, 
     PERSON.FIRSTNAME, 
     PERSON.MIDDLENAME
    FROM PERSON_VIEW PERSON
    LEFT JOIN DRIVERLICENSE_VIEW DRIVERLICENSE ON DRIVERLICENSE.PERSONID = PERSON.PERSONID 
    AND ((trunc(SYSDATE) - DRIVERLICENSE.UPDATED_DT <= 1000))
    AND DRIVERLICENSE_EXP_DT = (SELECT MAX(DRIVERLICENSE_EXP_DT)   
           FROM DRIVERLICENSE_VIEW PPT WHERE PPT.PERSONID = DRIVERLICENSE.PERSONID)
    

    【讨论】:

      猜你喜欢
      • 2013-01-12
      • 1970-01-01
      • 2012-12-04
      • 2016-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-28
      相关资源
      最近更新 更多