【问题标题】:Alternative way to left join in SQL ORACLE DB在 SQL ORACLE DB 中左连接的另一种方法
【发布时间】:2015-06-06 10:38:34
【问题描述】:

如果我在查询下面运行查询:

SELECT day.M_CMP_TYPO AS M_CMP_TYPO,
        day.M_SPTCV as M_SPTCV,
       day.M_CNT_VS2 AS M_CNT_VS2,
       day.M_CNT_ORG AS M_CNT_ORG,
       day.M_PL_CGR2 AS M_PL_CGR2,
       day.M_PL_CGU2 AS M_PL_CGU2,
       day.M_PL_CSFI2 AS M_PL_CSFI2,
       day.M_PL_FTFI2 AS M_PL_FTFI2,
       day.M_PL_RVR2 AS M_PL_RVR2,
       day.M_PL_RVU2 AS M_PL_RVU2,
       day.M_TRN_FMLY AS M_TRN_FMLY,
       day.M_TRN_GRP AS M_TRN_GRP,
       day.M_TRN_TYPE AS M_TRN_TYPE,
       day.M_CNT_VS2 AS M_CNT_VS2,
       day.M_C_CUR_PL AS M_C_CUR_PL,
       day.M_INSTRLABEL AS M_INSTRLABEL,
       day.M_NB AS M_NB,
       day.M_PL_INSCUR AS M_PL_INSCUR,
       day.M_TP_CNTRPLB AS M_TP_CNTRPLB,
       day.M_TP_PFOLIO AS M_TP_PFOLIO,
       day.M_ECO_PL AS M_ECO_PL,
       day.M_CNT_ID AS M_CNT_ID,
       day.M_ECO_PL_USD AS M_ECO_PL_USD,
       day.M_POS_CURR2 AS M_POS_CURR2,
       day.M_CURR2 AS M_CURR2,
       day.M_TP_QTYEQ AS M_TP_QTYEQ,
       day.M_TP_UQTYEQ AS M_TP_UQTYEQ,
       day.M_TP_LQTY32 AS M_TP_LQTY32,
       day.M_TP_UQTY AS M_TP_UQTY,


     --day.M_ECO_PL - daily.M_ECO_PL AS DAILY_VAR,
         --day.M_ECO_PL - month.M_ECO_PL AS MTD,
     day.M_ECO_PL - year.M_ECO_PL AS YTD,



--day.M_SPTCV * (day.M_ECO_PL - daily.M_ECO_PL) as DAILY_VAR_USD,
--day.M_SPTCV * (day.M_ECO_PL - month.M_ECO_PL) as MTD_USD,
day.M_SPTCV * (day.M_ECO_PL - year.M_ECO_PL) as YTD_USD



  FROM RT_PLVAR_REP day
  LEFT JOIN RT_PLVAR_REP year ON day.M_NB = year.M_NB
    --LEFT JOIN RT_PLVAR_REP month ON day.M_NB = month.M_NB
  --LEFT JOIN RT_PLVAR_REP daily ON day.M_NB = daily.M_NB

WHERE day.M_REF_DATA = 18
AND   year.M_REF_DATA = 20
--AND   month.M_REF_DATA = 0
--AND   daily.M_REF_DATA = 0

它返回预期的行为,这意味着它返回 27 行,知道数据库中存在 year.M_REF_DATA = 20。否则,如果我运行这个,我就没有价值了。 由于表中不存在 M_REF_DATA=0,我希望此查询返回 27 行,但相关列应返回 null,但事实并非如此。

我尝试将 Where 替换为 AND,它也不起作用。它返回了 1728 行,这是一个错误的答案,它应该返回 11。我的问题是为什么左连接没有按预期工作?

SELECT day.M_CMP_TYPO AS M_CMP_TYPO,
            day.M_SPTCV as M_SPTCV,
           day.M_CNT_VS2 AS M_CNT_VS2,
           day.M_CNT_ORG AS M_CNT_ORG,
           day.M_PL_CGR2 AS M_PL_CGR2,
           day.M_PL_CGU2 AS M_PL_CGU2,
           day.M_PL_CSFI2 AS M_PL_CSFI2,
           day.M_PL_FTFI2 AS M_PL_FTFI2,
           day.M_PL_RVR2 AS M_PL_RVR2,
           day.M_PL_RVU2 AS M_PL_RVU2,
           day.M_TRN_FMLY AS M_TRN_FMLY,
           day.M_TRN_GRP AS M_TRN_GRP,
           day.M_TRN_TYPE AS M_TRN_TYPE,
           day.M_CNT_VS2 AS M_CNT_VS2,
           day.M_C_CUR_PL AS M_C_CUR_PL,
           day.M_INSTRLABEL AS M_INSTRLABEL,
           day.M_NB AS M_NB,
           day.M_PL_INSCUR AS M_PL_INSCUR,
           day.M_TP_CNTRPLB AS M_TP_CNTRPLB,
           day.M_TP_PFOLIO AS M_TP_PFOLIO,
           day.M_ECO_PL AS M_ECO_PL,
           day.M_CNT_ID AS M_CNT_ID,
           day.M_ECO_PL_USD AS M_ECO_PL_USD,
           day.M_POS_CURR2 AS M_POS_CURR2,
           day.M_CURR2 AS M_CURR2,
           day.M_TP_QTYEQ AS M_TP_QTYEQ,
           day.M_TP_UQTYEQ AS M_TP_UQTYEQ,
           day.M_TP_LQTY32 AS M_TP_LQTY32,
           day.M_TP_UQTY AS M_TP_UQTY,


         day.M_ECO_PL - daily.M_ECO_PL AS DAILY_VAR,
             day.M_ECO_PL - month.M_ECO_PL AS MTD,
         day.M_ECO_PL - year.M_ECO_PL AS YTD,



    day.M_SPTCV * (day.M_ECO_PL - daily.M_ECO_PL) as DAILY_VAR_USD,
    day.M_SPTCV * (day.M_ECO_PL - month.M_ECO_PL) as MTD_USD,
    day.M_SPTCV * (day.M_ECO_PL - year.M_ECO_PL) as YTD_USD



      FROM RT_PLVAR_REP day
      LEFT JOIN RT_PLVAR_REP year ON day.M_NB = year.M_NB
        LEFT JOIN RT_PLVAR_REP month ON day.M_NB = month.M_NB
      LEFT JOIN RT_PLVAR_REP daily ON day.M_NB = daily.M_NB

    WHERE day.M_REF_DATA = 18
    AND   year.M_REF_DATA = 0
    AND   month.M_REF_DATA = 0
    AND   daily.M_REF_DATA = 0

【问题讨论】:

  • 通过在 WHERE 中说 year.M_REF_DATA = 0,您要求该值存在。考虑将 AND 移动到它们各自的 ON 之下,或者将子句包装在定义如何处理 NULL 的逻辑中。例如:NVL(year.M_REF_DATA, 0) = 0.

标签: sql oracle select left-join where


【解决方案1】:

这是第一个查询中的 fromwhere 子句:

FROM RT_PLVAR_REP day LEFT JOIN
     RT_PLVAR_REP year
     ON day.M_NB = year.M_NB
WHERE day.M_REF_DATA = 18 AND year.M_REF_DATA = 20

where 子句将LEFT JOIN 转换为INNER JOINyear.M_REF_DATA 的值为 NULL,因此条件不成立。

对于LEFT JOIN,条件应放在ON 子句中:

FROM RT_PLVAR_REP day LEFT JOIN
     RT_PLVAR_REP year
     ON day.M_NB = year.M_NB AND year.M_REF_DATA = 20
WHERE day.M_REF_DATA = 18

第一个表的条件应该保留在WHERE

【讨论】:

    【解决方案2】:

    对于外连接,您需要将过滤条件移动到连接:

      FROM RT_PLVAR_REP day
      LEFT JOIN RT_PLVAR_REP year 
        ON day.M_NB = year.M_NB
           AND year.M_REF_DATA = 0
      LEFT JOIN RT_PLVAR_REP month 
        ON day.M_NB = month.M_NB
           AND month.M_REF_DATA = 0
      LEFT JOIN RT_PLVAR_REP daily 
        ON day.M_NB = daily.M_NB
           AND daily.M_REF_DATA = 0
    WHERE day.M_REF_DATA = 18
    

    这告诉数据库您只想在存在行时强制执行该条件。

    【讨论】:

      猜你喜欢
      • 2020-09-28
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2021-05-20
      • 2012-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多