【问题标题】:Should I use an SQL full outer join for this?我应该为此使用 SQL 完全外连接吗?
【发布时间】:2022-01-06 12:21:47
【问题描述】:

考虑下表:

表 A:

DOC_NUM
DOC_TYPE
RELATED_DOC_NUM
NEXT_STATUS
...

表 B:

DOC_NUM
DOC_TYPE
RELATED_DOC_NUM
NEXT_STATUS
...

DOC_TYPENEXT_STATUS 列在两个表之间具有不同的含义,尽管 NEXT_STATUS = 999 在这两个表中都表示“关闭”。此外,在某些条件下,每个表中都会有一条记录,并引用另一个表中的相应条目(即RELATED_DOC_NUM 列)。

我正在尝试创建一个查询,该查询将从满足以下条件的两个表中获取数据:

A.RELATED_DOC_NUM = B.DOC_NUM
A.DOC_TYPE = "ST"
B.DOC_TYPE = "OT"
A.NEXT_STATUS < 999 OR B.NEXT_STATUS < 999

A.DOC_TYPE = "ST" 表示将库存从一个工厂转移到另一个工厂的转移订单。 B.DOC_TYPE = "OT" 表示在接收工厂对转移库存的相应收货。

我们希望从存在 ST/OT 对的任一表中获取记录,其中一个或两个条目关闭(即NEXT_STATUS &lt; 999)。

我假设我需要使用 FULL OUTER 连接来完成此操作。如果这是错误的假设,请让我知道我应该怎么做。

更新(2021 年 11 月 30 日):

我相信@Caius Jard 是正确的,因为它不需要是外部连接。应该总是有 ST/OT 对。

我的查询如下:

SELECT <columns>
FROM A LEFT JOIN B
ON
    A.RELATED_DOC_NUM = B.DOC_NUM
WHERE
    A.DOC_TYPE IN ('ST') AND
    B.DOC_TYPE IN ('OT') AND
    (A.NEXT_STATUS < 999 OR B.NEXT_STATUS < 999)

这有意义吗?

更新 2(2021 年 11 月 30 日):

实际情况是,这些是 JD Edwards ERP 应用程序正在使用的 DB2 数据库表。我知道查看表定义的唯一方法是使用网站http://www.jdetables.com/,输入表 ID 并按回车键运行搜索。它会返回有关表及其列的大量信息。

表 A 真的是 F4211,表 B 真的是 F4311

现在,我已经简化了查询以使其保持简单并将变量保持在最低限度。这是我目前拥有的:

SELECT CAST(F4211.SDDOCO AS VARCHAR(8)) AS SO_NUM,
       F4211.SDRORN AS RELATED_PO,
       F4211.SDDCTO AS SO_DOC_TYPE,
       F4211.SDNXTR AS SO_NEXT_STATUS,
       CAST(F4311.PDDOCO AS VARCHAR(8)) AS PO_NUM,
       F4311.PDRORN AS RELATED_SO,
       F4311.PDDCTO AS PO_DOC_TYPE,
       F4311.PDNXTR AS PO_NEXT_STATUS
FROM   PROD2DTA.F4211 AS F4211
       INNER JOIN PROD2DTA.F4311 AS F4311
         ON F4211.SDRORN = CAST(F4311.PDDOCO AS VARCHAR(8))
WHERE  F4211.SDDCTO IN ( 'ST' )
       AND F4311.PDDCTO IN ( 'OT' )

故事的另一部分是我正在使用一个报告包,它允许您定义数据的“虚拟”视图。虚拟视图允许报表开发人员指定要使用的 SQL。这是我使用 SQL 的应用程序。当我设置 SQL 时,必须执行一个验证步骤。如果 SQL 被验证,它将返回一组有限的结果。

当我输入上面的查询并验证它时,它说没有结果,这是没有意义的。我猜是数据转换导致了这个问题,但不确定。

更新 3(2021 年 11 月 30 日):

故事的另一个转折点。相关文档编号不仅定义为字符串值,而且包含前导零。这在两个表中都是正确的。主文档编号(在两个表中)被定义为数值,因此没有前导零。我不知道开发 JDE 的人为什么会这样做,但事实就是如此。

所以,两个表之间有 匹配记录符合条件,但我认为我没有得到任何结果,因为当我将数字转换为字符串时,它不匹配,因为一个值是"12345",而另一个是"00012345"

在进行等号检查之前,我可以用零填充数字 -> 字符串值吗?

更新 4(2021 年 12 月 2 日):

最终能够通过将数字文档编号转换为左填充字符串来使查询工作。

SELECT <columns>
FROM   PROD2DTA.F4211 AS F4211
       INNER JOIN PROD2DTA.F4311 AS F4311
         ON F4211.SDRORN = RIGHT(CONCAT('00000000', CAST(F4311.PDDOCO AS VARCHAR(8))), 8)
WHERE  F4211.SDDCTO IN ( 'ST' )
       AND F4311.PDDCTO IN ( 'OT' )
       AND ( F4211.SDNXTR < 999
              OR F4311.PDNXTR < 999 )

【问题讨论】:

  • 可以展示你的尝试吗?
  • 对我来说似乎是内联;您没有表明 A 或 B 可能丢失并且它是有效的,您只是表明有效条件是“A 存在状态
  • @Caius Jard - 我相信你是对的。我过牌了,应该总是有 ST/OT 对。
  • 很少有需要完全外连接的情况。据我所知,最常见的用途是查找缺失的关系和/或查找表之间不匹配的记录值。
  • 它说没有结果 - 那不是数据转换错误吗?如果没有结果,或者两个表都缺少数据,或者没有表数据与连接匹配,则对 F4211 和 F4311 执行单独的查询以检查相关数据是否存在

标签: sql db2 jdedwards


【解决方案1】:

您应该按如下方式编写查询:

SELECT <columns>
FROM A INNER JOIN B
ON
    A.RELATED_DOC_NUM = B.DOC_NUM
WHERE
    A.DOC_TYPE IN ('ST') AND
    B.DOC_TYPE IN ('OT') AND
    (A.NEXT_STATUS < 999 OR B.NEXT_STATUS < 999)

LEFT join 是 OUTER join 的一种; LEFT JOIN 通常是 LEFT OUTER JOIN 的缩写)。 OUTER 的意思是“由于没有匹配项,每一列中的一侧可能都有空值”。最关键的是,问题中发布的代码(使用 LEFT JOIN,但随后具有 WHERE some_column_from_the_right_table = some_value)作为 INNER 连接运行,因为 LEFT OUTER 进程插入的任何 NULL 都会被 WHERE 子句取消

【讨论】:

  • 我已按照建议修改了 SQL。当我运行查询时,我收到“数据转换或数据映射错误”。我认为问题可能与 DOC_NUM 字段被定义为数字,而 RELATED_DOC_NUM 字段被定义为字符串有关。转换一个或另一个以匹配类型的最佳方法是什么?
  • 嗯..数字字段肯定会转换为字符串,但字符串不一定会转换为数字。您还没有说正在使用什么 DB,但我从错误中猜测它是 DB2; CAST(B.DOC_NUM as VARCHAR) - 表示如果related_doc_num 是一个字符串是错误的,它实际上只包含数字字符串/与DOC_NUM 相关,你应该将它转换为数字
  • 它是 DB2 作为 JDEdwards ERP 的后备数据存储。我一直在尝试将字符串值转换为数字,但仍然出现错误。
  • 但是如果其中一行的文档编号为“helloworld”怎么办-您将如何将其转换为数字?这就是为什么我说一个数字总是转换成一个字符串,但一个搅拌器并不总是转换成一个数字
  • 有道理。因此,我将其转换为将数字文档编号转换为与字符串相关的文档编号。仍然出现数据转换或映射错误。
【解决方案2】:

有关我如何解决“数据转换或映射”错误的详细信息,请参阅更新 4。

【讨论】:

    猜你喜欢
    • 2012-01-06
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多