【问题标题】:multiple implicit joins and explicit joins in a query [closed]查询中的多个隐式连接和显式连接 [关闭]
【发布时间】:2013-03-04 10:50:08
【问题描述】:

我有一个问题:

SELECT THDR.FILENAME,
       SOURCE.TXN_SOURCE_CD AS TXN_SOURCE_CD,
       SOURCE.DESCR as TXN_SOURCE,
       THDR.TXN_HEADER_ID,
       THDR.TXN_HEADER_EXT_ID,
       THDR.TXN_HEADER_DTTM,
       THDR.UPLOAD_DTTM,
       L.DESCR,
       NVL(SUM(TDTL.TXN_VOL), 0) TOTAL_VOLUME
  FROM ci_lookup_val_l L,
       ci_txn_source_l source,
       CI_TXN_HEADER   THDR
  LEFT JOIN ci_txn_detail TDTL 
  ON THDR.TXN_HEADER_ID = TDTL.TXN_HEADER_ID        

 WHERE TRIM(SOURCE.TXN_SOURCE_CD) = TRIM(TDTL.TXN_SOURCE_CD)
   AND SOURCE.LANGUAGE_CD = 'ENG'      
   AND L.FIELD_NAME = 'TXN_HEADER_STATUS'
   AND THDR.BO_STATUS_CD = L.FIELD_VALUE
   AND L.LANGUAGE_CD = 'ENG'
   AND THDR.TXN_HEADER_ID='22222228'
 GROUP BY THDR.FILENAME,SOURCE.DESCR,THDR.TXN_HEADER_ID,THDR.TXN_HEADER_EXT_ID,THDR.TXN_HEADER_DTTM,THDR.UPLOAD_DTTM,L.DESCR,SOURCE.TXN_SOURCE_CD

如您所见,此查询有多个隐式连接和 1 个显式连接。这是我第一次使用这种查询,但它可以编译。但是,此查询中的左连接不起作用。也就是说,如果我在 TDTL 中没有与 THDR 上的记录对应的记录,则查询不会返回任何行。

你能帮我修一下吗?

【问题讨论】:

  • 如果你正确阅读问题,你会发现查询没有给出任何错误信息,而是获取了错误的数据!
  • 删除 WHERE,验证您的 JOINS 确实按预期加入,然后一次将其放回一个条件。如果没有数据样本以及预期结果和实际结果之间的详细比较,任何人都无法回答这个问题。

标签: sql database oracle join


【解决方案1】:

我的建议是更改您的查询以对每个查询都使用显式联接:

SELECT THDR.FILENAME,
       SOURCE.TXN_SOURCE_CD AS TXN_SOURCE_CD,
       SOURCE.DESCR as TXN_SOURCE,
       THDR.TXN_HEADER_ID,
       THDR.TXN_HEADER_EXT_ID,
       THDR.TXN_HEADER_DTTM,
       THDR.UPLOAD_DTTM,
       L.DESCR,
       NVL(SUM(TDTL.TXN_VOL), 0) TOTAL_VOLUME
FROM ci_lookup_val_l L
INNER JOIN CI_TXN_HEADER   THDR
  ON THDR.BO_STATUS_CD = L.FIELD_VALUE
LEFT JOIN ci_txn_detail TDTL 
  ON THDR.TXN_HEADER_ID = TDTL.TXN_HEADER_ID       
LEFT JOIN ci_txn_source_l source
  on TRIM(SOURCE.TXN_SOURCE_CD) = TRIM(TDTL.TXN_SOURCE_CD)
  AND SOURCE.LANGUAGE_CD = 'ENG' 
WHERE L.FIELD_NAME = 'TXN_HEADER_STATUS' 
   AND L.LANGUAGE_CD = 'ENG'
   AND THDR.TXN_HEADER_ID='22222228'
GROUP BY THDR.FILENAME,
  SOURCE.DESCR,
  THDR.TXN_HEADER_ID,
  THDR.TXN_HEADER_EXT_ID,
  THDR.TXN_HEADER_DTTM,
  THDR.UPLOAD_DTTM,
  L.DESCR,
  SOURCE.TXN_SOURCE_CD

【讨论】:

  • 这不起作用,因为使用了 TRIM。通过交换合并答案以纠正 urs
  • @MozenRath 你能详细说明不起作用吗?您收到错误消息吗?
  • 我没有得到任何行。这意味着某些左连接无法正常工作
  • @MozenRath 我将SOURCE.LANGUAGE_CD = 'ENG' 移动到连接条件,因为它会导致它的行为类似于INNER JOIN。查看我的编辑。
【解决方案2】:

问题是这种情况:

 WHERE TRIM(SOURCE.TXN_SOURCE_CD) = TRIM(TDTL.TXN_SOURCE_CD)

TDTL中没有匹配的条目时,TDTL.TXN_SOURCE_CD将是NULL,记录将被拒​​绝。

您需要重新考虑涉及SOURCE 的(隐式内部)连接。

【讨论】:

  • 不适用于 IS NULL,并且不确定如何将条件移动到左连接
【解决方案3】:

您可以在语句中使用以下子句,

WHERE TRIM(NVL(SOURCE.TXN_SOURCE_CD, 'NULL')) = TRIM(NVL(TDTL.TXN_SOURCE_CD, 'NULL'))

如果您还想检查空值。看看这是否有效

【讨论】:

    【解决方案4】:

    这很难理解,但切换到使用一致的连接语法会有所帮助。提供数据和预期结果会有所帮助,所以这在很大程度上是一种猜测。但问题似乎出在:

    WHERE TRIM(SOURCE.TXN_SOURCE_CD) = TRIM(TDTL.TXN_SOURCE_CD)
    

    由于在 SOURCETDTL 之间强制执行内连接条件,THDRTDTL 之间的左外连接实际上也变成了内连接。你真的需要把它移到外部连接中。

    这样的东西看起来应该可以满足您的需求,但实际上仍然只是猜测:

    SELECT THDR.FILENAME,
           SOURCE.TXN_SOURCE_CD AS TXN_SOURCE_CD,
           SOURCE.DESCR as TXN_SOURCE,
           THDR.TXN_HEADER_ID,
           THDR.TXN_HEADER_EXT_ID,
           THDR.TXN_HEADER_DTTM,
           THDR.UPLOAD_DTTM,
           L.DESCR,
           NVL(SUM(TDTL.TXN_VOL), 0) TOTAL_VOLUME
      FROM ci_lookup_val_l L
      JOIN ci_txn_source_l SOURCE
        ON SOURCE.LANGUAGE_CD = L.LANGUAGE_CD
      JOIN CI_TXN_HEADER THDR
        ON THDR.BO_STATUS_CD = L.FIELD_VALUE
      LEFT JOIN ci_txn_detail TDTL 
        ON TDTL.TXN_HEADER_ID = THDR.TXN_HEADER_ID        
       AND TRIM(TDTL.TXN_SOURCE_CD) = TRIM(SOURCE.TXN_SOURCE_CD)
     WHERE L.FIELD_NAME = 'TXN_HEADER_STATUS'
       AND L.LANGUAGE_CD = 'ENG'
       AND THDR.TXN_HEADER_ID = '22222228'
     GROUP BY THDR.FILENAME,SOURCE.DESCR,THDR.TXN_HEADER_ID,THDR.TXN_HEADER_EXT_ID,
               THDR.TXN_HEADER_DTTM,THDR.UPLOAD_DTTM,L.DESCR,SOURCE.TXN_SOURCE_CD;
    

    但是,如果 TRIM(TDTL.TXN_SOURCE_CD)TRIM(SOURCE.TXN_SOURCE_CD) 可能为 null,则该比较将不起作用,但完全不清楚您想要发生什么。你可以这样做:

      LEFT JOIN ci_txn_detail TDTL 
        ON TDTL.TXN_HEADER_ID = THDR.TXN_HEADER_ID        
       AND ((TRIM(TDTL.TXN_SOURCE_CD) IS NULL AND TRIM(SOURCE.TXN_SOURCE_CD) IS NULL)
           OR (TRIM(TDTL.TXN_SOURCE_CD) = TRIM(SOURCE.TXN_SOURCE_CD)))
    

    ...但真的不确定这会给出您期望的答案(不管是什么!)。

    【讨论】:

      【解决方案5】:

      感谢所有回答问题的人。我结合了大多数答案提出的建议来找到实际的解决方案:

      SELECT THDR.FILENAME,
             SOURCE.TXN_SOURCE_CD AS TXN_SOURCE_CD,
             SOURCE.DESCR as TXN_SOURCE,
             THDR.TXN_HEADER_ID,
             THDR.TXN_HEADER_EXT_ID,
             THDR.TXN_HEADER_DTTM,
             THDR.UPLOAD_DTTM,
             L.DESCR,
             NVL(SUM(TDTL.TXN_VOL), 0) TOTAL_VOLUME
        FROM ci_lookup_val_l L,
             CI_TXN_HEADER   THDR
        LEFT JOIN ci_txn_detail TDTL 
        ON THDR.TXN_HEADER_ID = TDTL.TXN_HEADER_ID        
        LEFT JOIN ci_txn_source_l source
        ON (TRIM(NVL(SOURCE.TXN_SOURCE_CD, 'NULL')) = TRIM(NVL(TDTL.TXN_SOURCE_CD, 'NULL')) AND SOURCE.LANGUAGE_CD = :LANGUAGE)
      
       WHERE L.FIELD_NAME = 'TXN_HEADER_STATUS'
         AND THDR.BO_STATUS_CD = L.FIELD_VALUE
         AND L.LANGUAGE_CD = :LANGUAGE
      
       GROUP BY THDR.FILENAME,SOURCE.DESCR,THDR.TXN_HEADER_ID,THDR.TXN_HEADER_EXT_ID,THDR.TXN_HEADER_DTTM,THDR.UPLOAD_DTTM,L.DESCR,SOURCE.TXN_SOURCE_CD;
      

      【讨论】:

      • 这是什么意思-NVL(SOURCE.TXN_SOURCE_CD, NULL)?就好像您说“如果 SOURCE.TXN_SOURCE_CD 为 null 则返回 null”,或者我错过了什么……您的意思是也许-NVL(SOURCE.TXN_SOURCE_CD, 'NULL')
      • sry 你是对的,我的错
      • 为什么它现在是SOURCE 的左连接?这是否意味着如果没有匹配的 TDTL 记录,TXN_SOURCE_IDTXN_SOURCE_CD 将为空白?
      • 是的。这就是我们想要的
      猜你喜欢
      • 2019-04-03
      • 2016-04-11
      • 1970-01-01
      • 1970-01-01
      • 2014-07-18
      • 2011-10-17
      • 2010-09-07
      • 1970-01-01
      • 2020-03-31
      相关资源
      最近更新 更多