繁体   English   中英

带有左外部联接子查询的Oracle问题

[英]Oracle issue with a left outer join subquery

我有一个SQL,它在左外部联接子查询中失败

ORA-01427: single-row subquery returns more than one row

这是left outer join查询片段:

 LEFT OUTER JOIN (aa.location) LOCATION
    ON (location_info_300.client_num = location.client_num
    AND location_info_300.source = location.source
    AND location_info_300.location_code = location.location_code
    AND 1 =
           (SELECT ROW_NUMBER()
                   OVER(PARTITION BY location_code, client_num, SOURCE
                        ORDER BY expiry_date DESC)
                      AS rec_order_by_expiry_desc
              FROM aa.location l2
             WHERE location.client_num = l2.client_num
               AND location.source = l2.source
               AND location.location_code = l2.location_code
               AND l2.expiry_date >=
                      TO_DATE('01-JAN-' || location_info_300.reporting_year,
                              'DD-MON-YYYY')
               AND l2.effective_date <=
                      TO_DATE('31-DEC-' || location_info_300.reporting_year,
                              'DD-MON-YYYY')))

我尝试通过在最后一个AND条件中进行以下更改来修复此问题:

1 = 
(SELECT rec_order_by_expiry_desc
  FROM (SELECT ROW_NUMBER() OVER (PARTITION BY LOCATION_CODE, CLIENT_NUM, SOURCE ORDER BY EXPIRY_DATE DESC) AS REC_ORDER_BY_EXPIRY_DESC
   FROM aa.LOCATION l2
  WHERE location.CLIENT_NUM = l2.CLIENT_NUM
    AND location.SOURCE = l2.SOURCE
    AND location.LOCATION_CODE = l2.LOCATION_CODE
    AND l2.EXPIRY_DATE >= TO_DATE('01-JAN-'||location_info_300.REPORTING_YEAR,'DD-MON-YYYY')
    AND l2.EFFECTIVE_DATE <= TO_DATE('31-DEC-'||location_info_300.REPORTING_YEAR,'DD-MON-YYYY'))
WHERE rec_order_by_expiry_desc = 1)

但是现在我收到以下错误:

ORA-00904: "LOCATION_INFO_300"."REPORTING_YEAR": invalid identifier

我不确定还有什么尝试。 我希望有人这样做!

我认为您基本上是在检查子查询中是否存在该行? 如果是这样,那么只需执行一个EXISTS

   LEFT OUTER JOIN (aa.location) LOC
                                 ON (location_info_300.client_num = loc.client_num
                                     AND location_info_300.source = loc.source
                                     AND location_info_300.location_code = loc.location_code
                                     AND exists (SELECT null
                                                 FROM   aa.location l2
                                                 WHERE  loc.client_num = l2.client_num
                                                 AND    loc.source = l2.source
                                                 AND    loc.location_code = l2.location_code
                                                 AND    l2.expiry_date >= TO_DATE('01-JAN-' || location_info_300.reporting_year, 'DD-MON-YYYY')
                                                 AND    l2.effective_date <= TO_DATE('31-DEC-' || location_info_300.reporting_year, 'DD-MON-YYYY')))

注意,我更改了aa.location表的别名,只是为了避免外部查询和子查询的aa.location表之间可能发生的冲突(最好确保别名与现有的标识符名称不同,以避免任何潜在的冲突范围冲突问题。此外,当您阅读查询时,它更易于理解)。

您的第一个子查询应该恰好返回一行,但它返回的行多。

这是因为您执行了分析功能,该功能实际上应该返回可变数量的行。 断言仅将返回一行的唯一方法是使用聚合函数或使用可确保做到这一点的条件。

关于第二个查询,请注意,您正在从给定上下文中不存在的表中调用字段。

如果要检查行是否存在,则应读入EXISTS函数,或者在子查询中使用COUNT。

编辑:这是第二个选项的示例(拳头已张贴):

(SELECT COUNT(*)
              FROM aa.location l2
             WHERE location.client_num = l2.client_num
               AND location.source = l2.source
               AND location.location_code = l2.location_code
               AND l2.expiry_date >= TO_DATE('01-JAN-' || location_info_300.reporting_year, 'DD-MON-YYYY')
               AND l2.effective_date <= TO_DATE('31-DEC-' || location_info_300.reporting_year, 'DD-MON-YYYY'))

请注意,我删除了PARTITION BY子句中的字段,并且没有将它们添加到GROUP BY中,因为它们与您仅需要一行的记录冲突。

检查1 =(获取最大有效日期的行号)只是检查这些条件是否存在最大有效日期,如果是,则将针对客户,来源和位置的组合返回所有行。 这是你想要的吗?

如果您想要具有最大失效日期的实际记录,则

 LEFT OUTER JOIN (aa.location) LOCATION
    ON (location_info_300.client_num = location.client_num
    AND location_info_300.source = location.source
    AND location_info_300.location_code = location.location_code
    AND location.expiry_date =
           (SELECT MAX(expiry_date)
              FROM aa.location l2
             WHERE location.client_num = l2.client_num
               AND location.source = l2.source
               AND location.location_code = l2.location_code
               AND l2.expiry_date >=
                      TO_DATE('01-JAN-' || location_info_300.reporting_year,
                              'DD-MON-YYYY')
               AND l2.effective_date <=
                      TO_DATE('31-DEC-' || location_info_300.reporting_year,
                              'DD-MON-YYYY')))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM