【问题标题】:JOIN Issue : Correct the SQL Statement to solve : ORA-01799: a column may not be outer-joined to a subqueryJOIN 问题:更正 SQL 语句以解决:ORA-01799:列可能未外连接到子查询
【发布时间】:2012-12-04 09:05:00
【问题描述】:

如下所示;我怎样才能实现 fx.ftf_validitystartdate= ... 这条线的价值,因为 oracle 不允许我在下面这样做 .

    select * from  acc_accounts acc
    join kp_paramcore p on
    acc.account_no = p.accountnum
    acc.suffix = p.suffixc
         LEFT JOIN ftf_rates fx
              ON p.maturestart = fx.ftf_vadealtsinir
             AND p.maturefinish = fx.ftf_vadeustsinir
             AND fx.statusrec = 'A'
             AND fx.currencycode = acc.currencsw_kod
             AND fx.status= 'A' 
  and  fx.ftf_validitystartdate= (SELECT MAX(ff.ftf_validitystartdate)
                                               FROM ftf_rates ff
                                              WHERE ff.status = 'A'
                                                AND ff.statusrec = 'A'
                                                AND v_CurrentDate BETWEEN ff.systemstartdate AND ff.systemfinishdate                                            AND ff.currencycode = acc.currencsw_kod
    )

【问题讨论】:

  • And 在您的复制粘贴查询中在 fx.status= 'A' 之后丢失?
  • oracle 版本 10g,也必须在 11g 上运行
  • 我假设您在 kp_paramcore 加入之后也缺少 on
  • @danihp:CTE 早在 Oracle 11g 之前就已经可用(我认为它们在 9.1 中可能更早引入 - 但它们在 10.x 中肯定可用)。 11.2 引入了 recursive CTE,在这种情况下不需要。
  • @a_horse_with_no_name,请查看我的答案。感谢您更正我的评论。

标签: sql oracle join left-join


【解决方案1】:

如果你把它切换到where 子句,它应该可以工作:

select *
from acc_accounts acc join
     kp_paramcore p
     on acc.account_no = p.accountnum and
        acc.suffix = p.suffixc LEFT JOIN
     ftf_rates fx
     ON p.maturestart = fx.ftf_vadealtsinir and
        p.maturefinish = fx.ftf_vadeustsinir and
        fx.statusrec = 'A' and
        fx.currencycode = acc.currencsw_kod and
        fx.status= 'A'
 where fx.ftf_validitystartdate= (SELECT MAX(ff.ftf_validitystartdate)
                                 FROM ftf_rates ff
                                 WHERE ff.status = 'A' and
                                       ff.statusrec = 'A'
                                       p.v_CurrentDate BETWEEN ff.systemstartdate AND ff.systemfinishdate                                            AND ff.currencycode = acc.currencsw_kod
                                )

但是,您失去了“左外连接”特征,因此您还需要添加:or fx.ftf_validitystartdate is null。我猜 v_CurrentDate 来自“p”。在列名之前使用表别名总是一个好主意。

但是,我质疑是否真的需要子查询。只有当子查询内部有多个满足条件的记录时才需要。否则,我认为您可以将 on 子句更改为:

    ON p.maturestart = fx.ftf_vadealtsinir and
       p.maturefinish = fx.ftf_vadeustsinir and
       fx.statusrec = 'A' and
       fx.currencycode = acc.currencsw_kod and
       fx.status= 'A'and
       p.v_CurrentDate BETWEEN fx.systemstartdate AND fx.systemfinishdate

【讨论】:

    【解决方案2】:

    我使用 CTE 发布了解决方法,并且仅在 Oracle 11g 中进行了测试。

    To make test I create this schema:

    create table t_a ( a int );
    create table t_b ( a int);
    create table t_c ( a int);
    
    insert into t_a values (1);
    insert into t_a values (2);
    insert into t_a values (3);
    
    insert into t_b values (1);
    insert into t_b values (2);
    insert into t_b values (3);
    
    insert into t_c values (1);
    insert into t_c values (2);
    insert into t_c values (3);
    

    此时我强制此查询出错:

    select * 
    from t_a
    left outer join t_b
      on t_a.a = t_b.a and
         t_b.a = ( select max( a )
                 from t_c);
    

    现在我用 CTE 重写查询:

    with cte (a ) as (
       select a
       from t_b
       where t_b.a = ( select min( a )
                 from t_c)
    )
    select * 
    from t_a
    left outer join cte
      on t_a.a = cte.a;
    

    第二个查询返回正确的结果。

    我用 CTE 重写你的查询:

    with CTE as (
       select * from ftf_rates 
       where ftf_validitystartdate= (SELECT MAX(ff.ftf_validitystartdate)
                                     FROM ftf_rates ff
                                     WHERE ff.status = 'A'
                                          AND ff.statusrec = 'A'
                                          AND v_CurrentDate BETWEEN ff.systemstartdate 
                                          AND ff.systemfinishdate                   
                                          AND ff.currencycode = acc.currencsw_kod )
    
    )
        select * from  acc_accounts acc
        join kp_paramcore p on
        acc.account_no = p.accountnum
        acc.suffix = p.suffixc
             LEFT JOIN CTE fx
                  ON p.maturestart = fx.ftf_vadealtsinir
                 AND p.maturefinish = fx.ftf_vadeustsinir
                 AND fx.statusrec = 'A'
                 AND fx.currencycode = acc.currencsw_kod
                 AND fx.status= 'A' 
    

    注意,仅在 Oracle 11g 中测试。见@a_horse_with_no_name 评论:

    @danihp:CTE 早在 Oracle 11g 之前就可以使用(我认为它们是 在 9.1 中引入可能更早 - 但它们绝对是 在 10.x 中可用)。 11.2 引入了不需要的递归 CTE 在这种情况下。 ——

    【讨论】:

      猜你喜欢
      • 2013-01-12
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-08
      • 2016-06-04
      • 2012-10-29
      相关资源
      最近更新 更多