在没有 INNER JOIN 的选择中使用表 BSEG

Posted

技术标签:

【中文标题】在没有 INNER JOIN 的选择中使用表 BSEG【英文标题】:Using the table BSEG in a selection without INNER JOIN 【发布时间】:2021-11-19 15:04:41 【问题描述】:

我正在尝试使用以下代码从表 BSEG 中选择字段 KOART

CONSTANTS: lc_d TYPE c VALUE 'D'.
    SELECT k~bukrs,
         k~belnr,
         k~budat,
         k~gjahr,
         k~buzei,
         k~kunnr,
         i~banks,
         i~bankl,
         i~bankn
    FROM bsid AS k
    INNER JOIN knbk AS i ON k~kunnr EQ i~kunnr
*    INNER JOIN bseg
    INTO TABLE @DATA(lt_data_knbk)
    WHERE k~bukrs IN @so_bukrs
    AND k~budat IN @so_budat
    AND k~blart IN @so_blart
*    AND bseg~koart = @lc_d.

通常我会为表添加 Inner join 语法,但由于 bseg 是一个集群表,它不接受内部连接选项,因此我不能使用字段 koart

谁知道,我怎样才能把BSEG的KOART字段放在上面的选择中?

非常感谢您的热心帮助!

【问题讨论】:

【参考方案1】:

As explained by József Szikszai,在这个特定的用例中实际上不需要内部连接,因为表 BSID 无论如何只包含客户文档。

但如果这里必要的,那么您将有两种选择:

首先是切换到 SAP HANA 作为数据库后端,因为这样所有的集群表都将转换为常规表。由于 SAP 宣布他们将从 2027 年开始为支持其他数据库收取额外费用,并在 2030 年完全放弃对非 HANA 的支持,因此从长远来看,您将无法解决这个问题。但由于 HANA 转换涉及成本和规划工作,如果您今天面临这个问题,这可能不是一个严肃的选择。

当您在不可避免的 HANA 转换之前需要临时解决方案时,还有第二种选择。您可以使用带有FOR ALL ENTRIES 条件的第二次选择来解决此问题。

SELECT bukrs,
     belnr,
     budat,
     gjahr,
     buzei,
     kunnr,
  FROM bsid     
  INTO TABLE @DATA(lt_data_bsid)
  WHERE bukrs IN @so_bukrs
  AND budat IN @so_budat
  AND blart IN @so_blart.

IF lt_data_bsid IS NOT INITIAL.
  SELECT bukrs,
         belnr,
         gjahr,
         buzei
    FROM bseg
    INTO TABLE @DATA(lt_bseg)
    FOR ALL ENTRIES IN @lt_data_bsid
    WHERE bukrs = @lt_data_bsid-bukrs
      AND belnr = @lt_data_bsid-belnr
      AND gjahr = @lt_data_bsid-gjahr
      AND buzei = @lt_data_bsid-buzei
      AND koart = @lc_d.
         
ENDIF.

请注意,这种方法存在许多问题:

您现在有两个内部表中的数据,而不是一个,因此您可能需要执行几个 READ TABLELOOP AT... WHERE 来将数据拼凑在一起。 两个 SELECT 而不是一个意味着到数据库服务器的两次网络往返而不是一次。您还错过了您的数据库可能能够为 JOIN 执行的大多数内部优化。这会增加程序的运行时间。 第一个 SELECT 可能会返回大量您不需要的数据,因此您可能会遇到内存问题。您可以通过使用数据库游标 (OPEN CURSOR) 和 FETCH 数据包中的结果来解决这个问题。但这会进一步降低性能。 在使用FOR ALL ENTRIES 时,永远不要忘记IF itab1 IS NOT INITIAL 检查。直观地说,如果查找表为空,就会假设根本没有接收到任何数据库行。但实际上会发生的是,提及FOR ALL ENTRIES 表的WHERE 条件会被完全忽略,您会收到所有 带有koart = 'D' 的表行。

但是,如果您必须对集群表进行 JOIN,那么很遗憾没有其他选择。

【讨论】:

【参考方案2】:

此选择不需要 KOART。 KOART EQ 'D'表示客户发帖,但BSID只包含客户发帖(见表的第三个字段是客户编号)。

【讨论】:

感谢您的回答。但是,我需要 KOART 来检查客户是否具有值“D”或 Debitoren。这是我的要求。 BSID 表中只有客户(Debitoren),您无需担心。另一方面,KNBK 表中只有客户银行账户,因此您受到双重保护。

以上是关于在没有 INNER JOIN 的选择中使用表 BSEG的主要内容,如果未能解决你的问题,请参考以下文章

SQLServer中 join 跟inner join的区别是啥?

left joinright join和inner join

left joinright join和inner join

SQL表连接查询(inner join(join)full joinleft joinright join)

SQL INNER JOIN - 根据另一行的值从另一个表中选择数据

MySQL INNER JOIN 从其他表中只选择一行