代码之家  ›  专栏  ›  技术社区  ›  Arnab

使用join转换内联查询

  •  1
  • Arnab  · 技术社区  · 8 年前

    我正在尝试替换当前的内联查询,并使用join替换相同的查询。然而,所得结果与实际结果不同。

    SELECT CLM.ID,
           EL.ERAC_ACTP_CD,
           CLM.ELCT_ID,
           CLM.CLMBT_ID,
           DECODE(CLM.PROVIDER,
                  NULL,
                  (SELECT NVL(NAME, '')
                     FROM PROVIDER
                    WHERE ID = PRVD_ID
                      AND EE_ID = CLM.EE_ID),
                  CLM.PROVIDER) PROVIDER_NAME,
           CB.CLAIM_TYPE,
           EL.ACCOUNT_NO
      FROM ELECTION EL, CLAIM CLM, CLAIM_BATCH CB
     WHERE EL.ID = CLM.ELCT_ID
       AND CLM.ID = 1
       AND EL.EE_ID = 1
       AND EL.ID = CLM.ELCT_ID
       AND CB.ID = CLM.CLMBT_ID;
    

    注-clm.prvd_id列值可以为空。

    最初我尝试使用下面的查询使用内部联接。这不起作用,因为prvd_id可以为空。因此,我没有收到任何输出,而在原始查询中收到了一行。

    SELECT CLM.ID,
               EL.ERAC_ACTP_CD,
               CLM.ELCT_ID,
               CLM.CLMBT_ID,
    DECODE(CLM.PROVIDER,
    NULL,
    PR.NAME,
    CLM.PROVIDER) PROVIDER_NAME,
    CB.CLAIM_TYPE,
    EL.ACCOUNT_NO
    FROM ELECTION EL, CLAIM CLM, CLAIM_BATCH CB, PROVIDER PR
    WHERE EL.ID = CLM.ELCT_ID
    AND CLM.ID = 1
    AND EL.EE_ID = 1
    AND EL.ID = CLM.ELCT_ID
    AND CB.ID = CLM.CLMBT_ID  
    AND  PR.ID = CLM.PRVD_ID
    

    你能建议我如何做到这一点吗?

    2 回复  |  直到 8 年前
        1
  •  3
  •   Boneist    8 年前

    要将标量子查询转换为联接,需要使用外部联接而不是内部联接,并使用相关谓词作为联接条件。

    在您的例子中,这意味着查询看起来像:

    SELECT clm.id,
         el.erac_actp_cd,
         clm.elct_id,
         clm.clmbt_id,
         COALESCE(clm.provider, pr.name) provider_name,
         cb.claim_type,
         el.account_no
    FROM   election el
           INNER JOIN claim clm ON el.id = clm.elct_id
           INNER JOIN claim_batch cb ON clm.clmbt_id = cb.id
           LEFT OUTER JOIN provider pr ON clm.ee_id = pr.ee_id AND pr.id = clm.prvd_id
    WHERE  clm.id = 1
    AND    el.ee_id = 1;
    

    注意,我已经将您的解码转换为合并,因为您想要显示clm.provider(如果不是空值)或pr.name(如果是空值)。coalesce只返回第一个非空值。

    我还将您的查询转换为使用ansi连接,而不是旧样式的连接;这使您更清楚地了解什么是连接条件,什么是谓词。

        2
  •  2
  •   Alex Poole    8 年前

    最初我尝试使用下面的查询使用内部联接。这不起作用,因为prvd_id可以为空。

    你需要使用 外面的 join,使用ansi语法要简单得多(尽管您无论如何都应该使用);类似于:

    SELECT CLM.ID,
      EL.ERAC_ACTP_CD,
      CLM.ELCT_ID,
      CLM.CLMBT_ID,
      DECODE(CLM.PROVIDER, NULL, PR.NAME, CLM.PROVIDER) PROVIDER_NAME,
      CB.CLAIM_TYPE,
      EL.ACCOUNT_NO
    FROM ELECTION EL
    JOIN CLAIM CLM ON CLM.ELCT_ID = EL.ID
    JOIN CLAIM_BATCH CB ON CB.ID = CLM.CLMBT_ID
    LEFT JOIN PROVIDER PR on PR.ID = CLM.PRVD_ID
    WHERE CLM.ID = 1
    AND EL.EE_ID = 1;
    

    这个

    DECODE(CLM.PROVIDER, NULL, PR.NAME, CLM.PROVIDER)
    

    也可以使用case表达式或 nvl() coalesce() :

    COALESCE(CLM.PROVIDER, PR.NAME)
    

    正如@bonest所指出的,您可能需要包含一个附加条件,该条件存在于子查询中,但不存在于您的连接尝试中:

    LEFT JOIN PROVIDER PR on PR.ID = CLM.PRVD_ID
    AND PR.EE_ID = CLM.EE_ID
    

    但不清楚你是不是故意漏掉了。