【问题标题】:Oracle-Conveting SQL to ANSI SQLOracle-将 SQL 转换为 ANSI SQL
【发布时间】:2016-09-18 01:03:17
【问题描述】:

这是关于将查询转换为 ANSI SQL。我尝试使用 Oracle 旧语法编写此查询,但它引发了以下错误,因此我最终更改了它,如下所示。经过研究,我发现ANSI SQL支持这样的要求。

错误:一个表最多可以外部连接到另一个表提示

这是我编写的查询,它正在运行,但如果有办法可以用 ANSI-SQL 或使用旧的外连接语法重写它,那就太好了。我正在寻找要重写的联合查询,因为 with 子句中的其他查询可以正常工作。

    WITH BOM_PARENT AS (
    SELECT MX.SAP_MATNR MATNR
         , TRIM(I.IPRODUCTION) IPRODUCTION
         , TRIM(I.IDRAWING) IDRAWING
         , TRIM(M.BCHLD) BCHLD
         , M.BSEQ BSEQ
         , PX.WERKS WERKS
         , M.BPSCP MENGE
         , UX.SAP_UOM MEINS
         , I.IUMS
     FROM XX_MAIN.XX_BPCS_IIM I
        , XX_MAIN.XX_BPCS_MPB M
        , XX_MAIN.XX_MATER_XREF MX
        , XX_MAIN.XX_TRUNK_XREF PX
        , XX_MAIN.XX_MP_UNIT_XREF UX
    WHERE TRIM(I.IPRODUCTION) = TRIM(M.BPROD) 
      AND TRIM(MX.PROD_MATNR) = TRIM(I.IPRODUCTION)
      AND MX.CONV_FACTOR = TO_CHAR(I.IUMCN) 
      AND I.IUMS  = UX.LEGACY_UOM
      AND UX.SOURCE = 'AP'
      AND I.SOURCE = PX.SOURCE
      AND I.ENTITY = PX.LEGACY_PLANT
      AND I.ENTITY = 'SG' 
      AND I.IITYP = '4'
      --AND PX.WERKS IN ('1379')
      AND MX.SAP_MTART <> 'ZPRD'
    )
    , BOM_CHILDS AS
    (
     SELECT  B.*,
             X.SAP_MATNR IDNRK
           , ROW_NUMBER () OVER ( PARTITION BY B.MATNR,B.WERKS ORDER BY B.MATNR,B.WERKS) ID_ITEM_NO  
           , X.PROD_MATNR IDNRK_IPRODUCTION
           , X.DRAWING_MATNR IDNRK_IDRAWING     
      FROM  BOM_PARENT B
          , XX_MAIN.XX_MATER_XREF X
    WHERE  B.BCHLD = TRIM(X.PROD_MATNR )
      AND X.SAP_MTART <> 'ZPRD'
      AND X.SOURCE = 'AP'
    )
    SELECT DISTINCT C.MATNR
         , C.IPRODUCTION
         , C.IDRAWING
         , C.WERKS
         , (C.ID_ITEM_NO*10) ID_ITEM_NO
         , C.BSEQ
         , C.IDNRK
         , C.IDNRK_IPRODUCTION
         , C.IDNRK_IDRAWING
         , C.MENGE BPSCP
         , STPO.MENGE  STPO_MENGE
         , C.MEINS MEINS
         , C.IUMS IUMS
         , STPO.MEINS STPO_MEINS
      FROM BOM_CHILDS C
         , XX_MAIN.XX_MAST MAST
         , XX_MAIN.XX_STPO STPO
      WHERE C.MATNR = MAST.MATNR
       AND MAST.STLNR = STPO.STLNR
       AND MAST.STLAN = '1'
       AND MAST.WERKS = C.WERKS
       AND STPO.IDNRK = C.IDNRK
    UNION
    SELECT DISTINCT C.MATNR
         , C.IPRODUCTION
         , C.IDRAWING
         , C.WERKS
         , (C.ID_ITEM_NO*10) ID_ITEM_NO
         , C.BSEQ
         , C.IDNRK
         , C.IDNRK_IPRODUCTION
         , C.IDNRK_IDRAWING
         , C.MENGE BPSCP
         , STPO.MENGE  STPO_MENGE
         , C.MEINS MEINS
         , C.IUMS IUMS
         , STPO.MEINS STPO_MEINS
      FROM BOM_CHILDS C
         , XX_MAIN.XX_MAST MAST
         , XX_MAIN.XX_STPO STPO
      WHERE C.MATNR = MAST.MATNR(+)
       AND MAST.STLNR = STPO.STLNR(+)
       AND MAST.STLAN(+) = '1'
       AND MAST.WERKS(+) = C.WERKS
       AND STPO.IDNRK IS NULL
    ORDER BY MATNR,WERKS,ID_ITEM_NO,BSEQ;

【问题讨论】:

    标签: sql oracle outer-join ansi-sql


    【解决方案1】:

    这部分可能是导致问题的原因:

      FROM BOM_CHILDS C
         , XX_MAIN.XX_MAST MAST
         , XX_MAIN.XX_STPO STPO
      WHERE C.MATNR = MAST.MATNR(+)
       AND MAST.STLNR = STPO.STLNR(+)
       AND MAST.STLAN(+) = '1'
       AND MAST.WERKS(+) = C.WERKS
       AND STPO.IDNRK IS NULL
    

    为了使这更容易一些,让我们重新排列 WHERE 子句以按表的关联方式对表进行排序:

    FROM BOM_CHILDS C
     , XX_MAIN.XX_MAST MAST
     , XX_MAIN.XX_STPO STPO
    -- Joining C to MAST
    WHERE C.MATNR = MAST.MATNR(+)
      AND C.WERKS = MAST.WERKS(+)
      AND MAST.STLAN(+) = '1'
    -- Joining MAST to STPO
      AND MAST.STLNR = STPO.STLNR(+)
      AND STPO.IDNRK IS NULL
    

    我们将C 加入MAST,使用C 作为“驱动程序”表,并从匹配的MAST 中提取数据(左连接):

    FROM BOM_CHILDS C
    LEFT JOIN XX_MAIN.XX_MAST MAST
      ON C.MANTR = MAST.MANTR
     AND C.WERKS = MAST.WERKS
     AND MAST.STLAN = '1'
    

    然后我们需要将STPO 添加到连接中:

    LEFT JOIN XX_MAIN.XX_STPO STPO
      ON MAST.STLNR = STPO.STLNR
     AND STPO.IDNRK IS NULL
    

    把它们放在一起,我们得到:

    FROM BOM_CHILDS C
    LEFT JOIN XX_MAIN.XX_MAST MAST
      ON C.MANTR = MAST.MANTR
     AND C.WERKS = MAST.WERKS
     AND MAST.STLAN = '1'
    LEFT JOIN XX_MAIN.XX_STPO STPO
      ON MAST.STLNR = STPO.STLNR
     AND STPO.IDNRK IS NULL
    

    也就是说,即使 (+) 适用于左/右/外连接,Oracle recommends not using it

    Oracle 建议您使用FROM 子句OUTER JOIN 语法而不是Oracle 连接运算符。使用 Oracle 连接运算符 (+) 的外连接查询受以下规则和限制的约束,不适用于 FROM 子句 OUTER JOIN 语法:...

    【讨论】:

    • 谢谢@Mr Llama ..我如何在 STPO.IDNRK = C.IDNRK 中获得非空值 stpo.idnrk 以及空值(我的联合查询中的第一个查询检索匹配的 IDNRK) .是否可以仅在一个查询中使用此逻辑而不是编写联合。
    • 这就是外连接的作用。在它匹配的地方,你得到一个值,当它不匹配时,你得到一个 NULL。将内部联接的结果与外部联接联合起来总是会得到与单独的外部联接相同的结果。
    • @Tina - 如果此答案有助于解决您的问题,请使用投票箭头下方的复选标记考虑 marking it as accepted。谢谢!
    • 当然@骆驼先生。然而,这是我没有工作的加入,我最终写了两个联合查询......请看看,让我知道你的输入。这引发了我在上面的问题中提到的错误: WHERE C.MATNR = MAST.MATNR(+) AND MAST.STLNR = STPO.STLNR(+) AND MAST.STLAN(+) = '1' AND MAST.WERKS(+ ) = C.WERKS AND STPO.IDNRK(+) = C.IDNRK.
    猜你喜欢
    • 2021-11-15
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 2018-04-18
    • 2020-04-28
    • 1970-01-01
    相关资源
    最近更新 更多