【问题标题】:DB2 left join query difficultiesDB2 左连接查询困难
【发布时间】:2017-10-11 18:42:46
【问题描述】:

我正在努力通过 iSeries 服务器上的 ODBC 准备一个相对简单的查询。无论我们正在创建的报告的联接是什么,我都希望它返回一段数据。这是查询:

  Select   SCDATA.SCCLNT.CCLNT,
  SCDATA.SCCLNT.CNAME,
  SCDATA.SCCLNT.CLTGRP As Group,
  CONCAT(TRIM(SCDATA.SCCLNT.CADD1), SCDATA.SCCLNT.CADD2) As Address1,
  CONCAT(TRIM(SCDATA.SCCLNT.CCITY), CONCAT(', ',
      CONCAT(TRIM(SCDATA.SCCLNT.CSTATE), CONCAT('  ', 
      TRIM(SCDATA.SCCLNT.CZIP)))))
      As Address2,
  SCDATA.SCACCT.GCLNT,
  SCDATA.SCACCT.GPLACE,
  SCDATA.SCACCT.GPLDAT,
  SCDATA.SCACCT.GACCT# As GACCTnum,
  CONCAT(TRIM(SCDATA.SCACCT.GLAST), CONCAT(', ', 
    TRIM(SCDATA.SCACCT.GFIRST))) As
    Debtor,
  CONCAT((Select 
     VARCHAR_FORMAT(Min(TIMESTAMP_FORMAT(Cast(SCDATA.SCACCT.GPLDAT
     As Char(10)), 'YYYYMMDD')), 'MM/DD/YYYY') From SCDATA.SCACCT
     Where SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501), CONCAT(' 
     - ', (Select 
     VARCHAR_FORMAT(Max(TIMESTAMP_FORMAT(Cast(SCDATA.SCACCT.GPLDAT As
     Char(10)), 'YYYYMMDD')), 'MM/DD/YYYY') From SCDATA.SCACCT
     Where SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501))) As 
     dateRange
From SCDATA.SCCLNT
  Left Outer Join SCDATA.SCACCT On 
    CDATA.SCACCT.GCLNT = SCDATA.SCCLNT.CCLNT
Where SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501 And
  SCDATA.SCCLNT.CLTGRP Like '######'

当 SCACCT 表返回值时,此查询工作正常,但我需要 SCCLNT 中的至少一行来填充报告中的客户详细信息。我们使用的报表软件 (DBExtra.net) 不支持每个报表的多个查询,因此必须将它们全部捆绑到一个查询中。

不幸的是,除了基本查询之外,SQL 并不是我的强项之一,因此我们将不胜感激。谢谢。

【问题讨论】:

  • 您的 where 子句中有与 SCACCT 中的列(您要外部连接的表)相关的条件,这意味着不会返回来自外部连接的空行。要么在连接子句中包含这些条件,要么在所有条件中包含 null 的可能性:(gpldat between x and y or gpldata is null)和(cltgrp like '######' or cltgrp is null)
  • 附注 - 请使用专属上限 (<) 进行日期/时间/时间戳查询,or risk unintended data

标签: sql db2


【解决方案1】:

确切地说,可能不是你想要的,但如果其他人因为我想到的原因发现这个问题:

以下是如何生成至少一行(仅重复相关部分):

From SYSIBM.DUAL
  Left Outer Join (
    Select *
    From SCDATA.SCCLNT
      Left Outer Join SCDATA.SCACCT On 
        CDATA.SCACCT.GCLNT = SCDATA.SCCLNT.CCLNT
    Where SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501 And
    SCDATA.SCCLNT.CLTGRP Like '######'
  ) t On 1 = 1

请注意我是如何将您的原始查询包装在一个名为 t 的派生表中的。这意味着:

  • 您必须处理不明确的列名
  • 您必须取消对 t 的列的引用,而不是从 SCCLNTSCACCT

SYSIBM.DUAL 保证始终只包含一行。

【讨论】:

    【解决方案2】:

    Left Outer Join SCDATA.SCACCTWhere SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501 之间存在矛盾。 您可以做的是将此WHERE 子句移至外部联接的ON 子句,因此日期标准在SCACCTSCCLNT 联接之前适用:

    From SCDATA.SCCLNT
      Left Outer Join SCDATA.SCACCT On 
        CDATA.SCACCT.GCLNT = SCDATA.SCCLNT.CCLNT And
        SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501 
    Where SCDATA.SCCLNT.CLTGRP Like '######' 
    

    请参阅Filter Table Before Applying Left Join 了解说明。

    【讨论】:

    • 效果很好,谢谢。现在我只需要弄清楚如何让我的报告消除详细信息部分中的空值:) 感谢您的帮助。
    • @Geoff 您可能需要添加 GROUP BY 以简化创建 dateRange 计算列的方式。如果要替换空值,请使用VALUE(expression,expression ... ),它返回第一个非空参数
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 2017-06-30
    相关资源
    最近更新 更多