0

我有一个在左外连接子查询中失败的 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

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

4

3 回答 3

3

我认为您基本上是在检查该行是否存在于子查询中?如果是这样,那么只需执行以下操作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 表之间可能存在的任何冲突(最好确保别名与现有标识符名称不同以避免任何潜在的范围冲突问题。此外,它使您在阅读查询时更容易理解)。

于 2015-10-28T17:29:40.963 回答
1

您的第一个子查询应该只返回一行,但它返回的不止一行。

这是因为您执行了一个分析函数,该函数本质上应该返回不同数量的行。断言只返回一行的唯一方法是使用聚合函数或使用可以确保这一点的条件。

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

如果您尝试检查行是否存在,您应该读入 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 中,因为它们与您只需要一行相冲突。

于 2015-10-28T17:31:43.720 回答
1

检查 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')))
于 2015-10-28T17:35:26.073 回答