简体   繁体   English

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

[英]Oracle issue with a left outer join subquery

I have a sql which is failing in a left outer join subquery with 我有一个SQL,它在左外部联接子查询中失败

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

Here is the left outer join query fragment: 这是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')))

I tried fixing it by doing the following change in the last AND criteria: 我尝试通过在最后一个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)

But now I am getting the following error: 但是现在我收到以下错误:

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

I am not sure what else to try. 我不确定还有什么尝试。 I hope someone does though! 我希望有人这样做!

I think you're basically checking if the row exists in the subquery? 我认为您基本上是在检查子查询中是否存在该行? If so, then just do an EXISTS : 如果是这样,那么只需执行一个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')))

NB I changed the alias of the aa.location table, just to avoid any possible conflicts between the outer and sub-query's aa.location tables (much better to make sure that aliases aren't the same as existing identifier names to avoid any potential scope clash issues. Also, it makes it easier to understand when you read the query). 注意,我更改了aa.location表的别名,只是为了避免外部查询和子查询的aa.location表之间可能发生的冲突(最好确保别名与现有的标识符名称不同,以避免任何潜在的冲突范围冲突问题。此外,当您阅读查询时,它更易于理解)。

Your first subquery should return exactly one row, but it returns more than one. 您的第一个子查询应该恰好返回一行,但它返回的行多。

This is because you perform an analytic function, which is essentially supposed to return a varied amount of rows. 这是因为您执行了分析功能,该功能实际上应该返回可变数量的行。 The only way to assert that only one row will be returned is using an aggregate function or using conditions that will assure that. 断言仅将返回一行的唯一方法是使用聚合函数或使用可确保做到这一点的条件。

Regarding the second query, note that you're calling a field from a table that doesn't exist in the given context. 关于第二个查询,请注意,您正在从给定上下文中不存在的表中调用字段。

If you're trying to check if a row exists or not, you should read into EXISTS function, or perhaps using COUNT in the subquery. 如果要检查行是否存在,则应读入EXISTS函数,或者在子查询中使用COUNT。

Edit: here is an example for the second option (the fist was already posted): 编辑:这是第二个选项的示例(拳头已张贴):

(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'))

Note that I removed the fields in the PARTITION BY clause and didn't add them in GROUP BY because they conflict with your need of only one row. 请注意,我删除了PARTITION BY子句中的字段,并且没有将它们添加到GROUP BY中,因为它们与您仅需要一行的记录冲突。

checking for 1= (get row number for max expiry date) just checks that there IS a max expiry date for those criteria, and if so then all rows would be returned for that combination of client, source, and location. 检查1 =(获取最大有效日期的行号)只是检查这些条件是否存在最大有效日期,如果是,则将针对客户,来源和位置的组合返回所有行。 Is this what you want? 这是你想要的吗?

If you want the actual record with the max expiry date, then 如果您想要具有最大失效日期的实际记录,则

 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