oracle 内部连接子查询与外部连接子查询问题

vngu2lb8  于 2023-04-20  发布在  Oracle
关注(0)|答案(2)|浏览(143)

下面的查询使用子查询内部连接,当子查询连接到EGP_SYSTEM_ITEMS ITM表时,我只需要从子查询中获取第一行(匹配)。我面临的问题是,当使用INNER JOIN时,查询不会返回下面的INVENTORY_ITEM_ID,即使它存在于子查询和外部(主)查询中。

SELECT ITM.INVENTORY_ITEM_ID, ORG.ORGANIZATION_CODE, PURCHASE_UOM_CODE.UNIT_OF_MEASURE
FROM EGP_SYSTEM_ITEMS ITM 

INNER JOIN      (SELECT DISTINCT UOMT.UNIT_OF_MEASURE, POL.ITEM_ID
                 FROM   INV_UNITS_OF_MEASURE_TL UOMT,
                        INV_UNITS_OF_MEASURE_B UOMB,
                        PO_HEADERS_ALL POH,
                        PO_LINES_ALL POL
                 WHERE  POH.PO_HEADER_ID = POL.PO_HEADER_ID
                        AND UOMB.UOM_CODE = POL.UOM_CODE
                        --AND POL.ITEM_ID = ITM.INVENTORY_ITEM_ID
                        AND UOMT.UNIT_OF_MEASURE_ID = UOMB.UNIT_OF_MEASURE_ID
                        AND UOMT.LANGUAGE = USERENV('LANG')                            
                        AND  POH.TYPE_LOOKUP_CODE = 'BLANKET'
                        AND ROWNUM = 1
                        --FETCH FIRST 1 ROWS ONLY
) PURCHASE_UOM_CODE ON PURCHASE_UOM_CODE.ITEM_ID =ITM.INVENTORY_ITEM_ID
WHERE ITM.INVENTORY_ITEM_ID= '11223'

如果我将上面的查询更改为使用LEFT OUTER连接,那么它将返回我期望的数据,但我担心在某些情况下它可能会获取比我需要的更多的信息。我相信子查询只是获取该表中的任意一行(与主查询不匹配),这就是查询不返回数据的原因。有没有一种方法可以让子查询在查询本身中引用ITM.INVENTORY_ITEM_ID列,而不仅仅是在Join条件中引用ITM.INVENTORY_ITEM_ID列?我尝试在子查询中加入POL.ITEM_ID = ITM.INVENTORY_ITEM_ID,但是它无法识别其中的外部列...
或者我应该在这种情况下只使用左外连接?

vawmfj5a

vawmfj5a1#

你在子查询中随机选择了一行,而它恰好不是你想要的外部查询块中的INVENTORY_ITEM_ID。你是对的,问题是带有ROWNUM过滤器的子查询上的常规连接。你必须将 predicate 驱动到视图中,而你不能用ROWNUM过滤器(或DISTINCT)来做这件事。

  • “子查询是否可以引用查询本身中的ITM.ITEM_NUMBER列,而不仅仅是在连接条件上?"*

查看CROSS APPLYOUTER APPLY

SELECT ITM.INVENTORY_ITEM_ID, ORG.ORGANIZATION_CODE, PURCHASE_UOM_CODE.UNIT_OF_MEASURE
  FROM EGP_SYSTEM_ITEMS ITM 
  CROSS APPLY (SELECT UOMT.UNIT_OF_MEASURE
                 FROM   INV_UNITS_OF_MEASURE_TL UOMT,
                        INV_UNITS_OF_MEASURE_B UOMB,
                        PO_HEADERS_ALL POH,
                        PO_LINES_ALL POL
                 WHERE  POH.PO_HEADER_ID = POL.PO_HEADER_ID
                        AND UOMB.UOM_CODE = POL.UOM_CODE
                        --AND POL.ITEM_ID = ITM.INVENTORY_ITEM_ID
                        AND UOMT.UNIT_OF_MEASURE_ID = UOMB.UNIT_OF_MEASURE_ID
                        AND UOMT.LANGUAGE = USERENV('LANG')                            
                        AND  POH.TYPE_LOOKUP_CODE = 'BLANKET'
                        AND POL.ITEM_ID =ITM.INVENTORY_ITEM_ID -- DRIVING PREDICATE HERE
                        AND ROWNUM = 1
            ) PURCHASE_UOM_CODE
 WHERE ITM.INVENTORY_ITEM_ID= '11223'

因为你只需要一个列,你可以简单地把子查询放在SELECT子句中,但是一旦你需要多个列,这是一个强大的技术。

z4bn682m

z4bn682m2#

DISTINCT在内部子查询中是没有意义的,因为你也在过滤where ROWNUM = 1,这样一行总是不同的。
看起来你可以将子查询移动到外部查询,然后使用ROW_NUMBER分析函数进行过滤:

SELECT INVENTORY_ITEM_ID,
       ORGANIZATION_CODE,
       UNIT_OF_MEASURE
FROM   (
  SELECT ITM.INVENTORY_ITEM_ID,
         ORG.ORGANIZATION_CODE,
         UOMT.UNIT_OF_MEASURE,
         ROW_NUMBER() OVER (
           PARTITION BY ITM.INVENTORY_ITEM_ID
           ORDER BY ROWNUM -- or something more appropriate
         ) AS rn
  FROM   EGP_SYSTEM_ITEMS ITM 
         INNER JOIN PO_LINES_ALL POL
         ON POL.ITEM_ID =ITM.INVENTORY_ITEM_ID
         INNER JOIN PO_HEADERS_ALL POH
         ON POH.PO_HEADER_ID = POL.PO_HEADER_ID
         INNER JOIN INV_UNITS_OF_MEASURE_B UOMB
         ON UOMB.UOM_CODE = POL.UOM_CODE
         INNER JOIN INV_UNITS_OF_MEASURE_TL UOMT
         ON UOMT.UNIT_OF_MEASURE_ID = UOMB.UNIT_OF_MEASURE_ID
  WHERE  UOMT.LANGUAGE = USERENV('LANG')                            
  AND    POH.TYPE_LOOKUP_CODE = 'BLANKET'
  AND    ITM.INVENTORY_ITEM_ID= '11223'
)
WHERE  rn = 1;

然而,由于你有过滤器INVENTORY_ITEM_ID= '11223',那么在ROW_NUMBER解析函数中只会使用一个分区,所以你可以将其简化为:

SELECT ITM.INVENTORY_ITEM_ID,
       ORG.ORGANIZATION_CODE,
       UOMT.UNIT_OF_MEASURE
FROM   EGP_SYSTEM_ITEMS ITM 
       INNER JOIN PO_LINES_ALL POL
       ON POL.ITEM_ID =ITM.INVENTORY_ITEM_ID
       INNER JOIN PO_HEADERS_ALL POH
       ON POH.PO_HEADER_ID = POL.PO_HEADER_ID
       INNER JOIN INV_UNITS_OF_MEASURE_B UOMB
       ON UOMB.UOM_CODE = POL.UOM_CODE
       INNER JOIN INV_UNITS_OF_MEASURE_TL UOMT
       ON UOMT.UNIT_OF_MEASURE_ID = UOMB.UNIT_OF_MEASURE_ID
WHERE  UOMT.LANGUAGE = USERENV('LANG')                            
AND    POH.TYPE_LOOKUP_CODE = 'BLANKET'
AND    ITM.INVENTORY_ITEM_ID= '11223'
AND    ROWNUM = 1;

相关问题