目录

一、字段的顺序会导致取数重复吗?

二、如果要在select的时候只获取字段的某一截数据,可以如何做?

三、在select的时候,可以A=B A=C B=C这样子JOIN吗?

四、如果在join的时候需要表1的字段某几位等于表2的字段的某几位,需要怎么做?

五、如果在select的时候,既要使用SUBSTRING 或者JOIN又要使用FOR ALL ENTRINES IN 怎么解决?

六、如果我将A表和B表连接了,但是只想取B表字段的值,不取A表字段的值,可以如何简单地写?

七、 这里用了一个left outer join

八、在SELECT的时候可以直接进行前导零补充吗?

九、记住SELECT SINGLE需要加前导零

十、使用FOR ALL ENTRIES IN的时候如果在写WHERE的条件时两个字段的长度不一致,可以如何做呢?


前导:这篇案例总结是平时做开发的时候的一些笔记记录,个人感觉非常有用!涵盖了大部分的开发场景,整篇文章是免费的,文章设置为“关注后可读”,这样我能更直观地了解它是否对大家有帮助,并决定未来是否产出更多类似内容。话不多说,我们直接看正文吧!

一、字段的顺序会导致取数重复吗?

不会,是我inner join的字段判断逻辑写少了,记住inner join、right join、left join的结果都是两个表的数量相乘。

二、如果要在select的时候只获取字段的某一截数据,可以如何做?

使用SUBSTRING,记得加空格,如果是取前6位,就写substring( 字段X,1,6 ) ,表示从第一位取值,取6个字符。

完整代码示例如下:

SELECT D~MATNR,D~VERPR,
      SUBSTRING( FKDAT_ANA,1,6 ) AS FKDAT_ANA,
      D~LFMON,
      SUM( CASE VBTYP_ANA
          WHEN 'N' THEN FKIMG * -1
          WHEN 'O' THEN FKIMG * -1
          ELSE FKIMG END ) AS FKIMG
        FROM VBRP
       INNER JOIN MARA ON MARA~MATNR = VBRP~MATNR
       INNER JOIN MBEWH AS D ON D~MATNR = VBRP~MATNR
       AND D~LFGJA = SUBSTRING( FKDAT_ANA,1,4 )
       AND D~LFMON = SUBSTRING( FKDAT_ANA,5,2 )
       WHERE MARA~MATKL = '20260'
       AND VBRP~WERKS IN @P_WERKS
       AND D~LFGJA = @GV_LYEAR
       AND D~LFMON BETWEEN 01 AND @P_MONAT
       AND D~BWKEY IN @P_WERKS
       AND VBRP~FKDAT_ANA BETWEEN @LV_DATELS  AND @LV_DATELD
       AND KTGRM = 'Z1'
       GROUP BY D~MATNR,D~VERPR,D~LFMON,FKDAT_ANA
       INTO TABLE @DATA(LT_VBRP2).

三、在select的时候,可以A=B A=C B=C这样子JOIN吗?

可以,代码如下:

 INNER JOIN T030 ON  T030~BKLAS = MBEW~BKLAS   

AND T030~BWMOD = T001K~BWMOD

完整代码示例如下:

 SELECT
      T030~KONTS,
      SKAT~TXT20,
      MBEW~MATNR,
      MBEW~BWKEY
      FROM MBEW
      INNER JOIN T001K ON  T001K~BWKEY = MBEW~BWKEY  "评估分组代码
      INNER JOIN T030 ON  T030~BKLAS = MBEW~BKLAS   AND T030~BWMOD = T001K~BWMOD
      LEFT JOIN SKAT ON skat~SAKNR = T030~KONTS AND skat~KTOPL = T030~KTOPL
      FOR ALL ENTRIES IN @GT_TAB
      WHERE T030~KTOSL = 'BSX'
      AND T030~KTOPL = '1000'
      AND MBEW~MATNR = @GT_TAB-MATNR
      AND MBEW~BWKEY = @GT_TAB-WERKS
    INTO TABLE @DATA(LT_T030).

四、如果在join的时候需要表1的字段某几位等于表2的字段的某几位,需要怎么做?

也是使用substring,

代码:SUBSTRING( C~KUNAG,5,6 ) = SUBSTRING( A~KUNNR,5,6 )

表明:C表的KUNAG字段的第5位开始,取6个字符,与C表的KUNNR字段的第5位开始,取6个字符,所对应的值相同。

一般可以用于需要连接的两个表中,一个表有前导零,另一个表没有前导零的时候使用,就可以不用去LOOP里面给其中一个表添加前导零了,但是没有试过效率哪个更高。

比如GT_ALV表里面没有前导零,后台表KNVV里面有前导零,这时不想去补充前导零,想直接在SELECT的时候截取或者补充前导零,如何做呢?

完整代码示例如下:

SELECT DISTINCT C~KUNAG,A~BZIRK ,B~BZTXT
      FROM KNVV AS A
      RIGHT JOIN @GT_ALV AS C ON ( SUBSTRING( C~KUNAG,5,6 ) = SUBSTRING( A~KUNNR,5,6 )
      OR C~KUNAG = SUBSTRING( A~KUNNR,5,6 ) )
      LEFT JOIN T171T AS B ON A~BZIRK = B~BZIRK
      WHERE A~VKORG = @P_BUKRS
*      AND B~SPRAS = @SY-LANGU
      INTO TABLE @DATA(LT_T171T_INNER).

这里因为GT_ALV里面既有一些有前导零又有一些没前导零,所以使用了一个OR。

五、如果在select的时候,既要使用SUBSTRING 或者JOIN又要使用FOR ALL ENTRINES IN 怎么解决?

既SUBSTRING 又FOR ALL ENTRINES IN时报错如下:

The addition SUBSTRING is not allowed in combination with FOR ALL

ENTRIES. Use JOINs or global temporary tables instead of FOR ALL ENTRIES.

可以使用INNER JOIN 内表 AS XX ON A= A.

如下:

这时候是会黄灯警告的,但是没关系,功能是正常的。

完整代码示例如下:

*   获取批次库存
      SELECT B~WERKS,B~LGORT,B~MATNR,CHARG,B~CLABS,'1' AS SOBKZ FROM MCHB AS B
        INNER JOIN @LT_TAB1 AS A ON B~WERKS = A~PLANT AND B~MATNR = A~MATNR AND B~LGORT = A~LGORT AND B~CLABS > '0'
        INTO TABLE @DATA(LT_MCHB).
*    获取寄售库存
      SELECT B~WERKS,B~LGORT,B~MATNR,CHARG,SUM( B~SLABS ) AS CLABS,'2' AS SOBKZ FROM MKOL AS B
      INNER JOIN @LT_TAB1 AS A ON B~WERKS = A~PLANT AND B~MATNR = A~MATNR AND B~LGORT = A~LGORT AND B~SLABS > '0'
      GROUP BY B~WERKS,B~LGORT,B~MATNR,B~CHARG
      INTO TABLE @DATA(LT_MKOL).

六、如果我将A表和B表连接了,但是只想取B表字段的值,不取A表字段的值,可以如何简单地写?

使用B~*

完整代码示例如下:

SELECT B~* FROM ZZT_BZJE AS B
    INNER JOIN @LT_LIST AS A ON
     B~WERKS = A~WERKS
    AND B~LIFNR = A~LIFNR
    AND B~MATNR = A~MATNR
    AND SUBSTRING( ZQIJIAN ,1,4 ) = A~GJAHR
    AND ZQIJIAN = SUBSTRING( A~BUDAT,1,6 )
    AND ZDELETE <> 'X'
    INTO TABLE @DATA(LT_BZJE).

而这个代码优化前的语句如下:

SELECT * FROM zzt_bzje
  FOR ALL ENTRIES IN @lt_list
  WHERE werks  = @lt_list-werks
    AND lifnr  = @lt_list-lifnr
    AND matnr  = @lt_list-matnr
    AND zqijian = @lt_list-budat+0(6) " 转换并截取
    AND zdelete <> 'X'
  INTO TABLE @DATA(lt_bzje).

这个优化前的代码好像会报错,应该是的。可能把@lt_list-budat+0(6)换成@lt_list-budat(6)应该就可行了。

七、这里用了一个left outer join

完整代码示例如下:

SELECT  P~MATNR,P~DWERK,P~KDAUF,P~KDPOS,K~AUFNR,K~RSNUM,RESB~MATNR AS MATN1
           FROM AFPO AS P
           INNER JOIN AFKO AS K ON  P~AUFNR = K~AUFNR
           LEFT OUTER JOIN RESB ON K~RSNUM = RESB~RSNUM
           WHERE P~KDAUF = @T_ITEMIN-VBELN
           AND  P~KDPOS = @T_ITEMIN-POSNR
           AND  P~MATNR = @T_ITEMIN-MATNR
           AND  P~DWERK = @T_ITEMIN-WERKS
           AND  SUBSTRING( RESB~MATNR,1,5 ) = '31002'
           INTO TABLE @DATA(LT_AD)."按单生产的物料数据

忘记了为什么使用outer join,总之是成功了的

八、在SELECT的时候可以直接进行前导零补充吗?

可以,但是没有试过和LOOP添加前导零哪个效率更高,只不过这里是自建的一个配置表,数据很少,所以忽略不计

完整代码示例如下:

SELECT
      ZTYPE,
      ZTEXT,
      LPAD( LTRIM( RACCT ,' ' ), 10, '0' ) AS RACCT
       FROM ZFIT0008
      WHERE ZTYPE = 'X001'
      INTO TABLE @DATA(LT_ZT08).

九、记住SELECT SINGLE需要加前导零

SELECT SINGLE 需要加前导零,不然会找不到数据

十、使用FOR ALL ENTRIES IN的时候如果在写WHERE的条件时两个字段的长度不一致,可以如何做呢?

有两个方法可以解决,一是可以在定义字段的时候将字段定义成一致,;二是使用CAST转换字段的数据类型,不过使用了CAST就需要将FOR ALL ENTRIES IN修改为 JOIN.

这里就是VBFA的RFMNG字段的类型是CURR 长度13带有3个小数,ACDOCA的MSL字段类型是CURR长度23带有3个小数。

方法一:

将内表里面的字段类型定义成和VBFA里面的一致,就不会报错了。

方法二、使用CAST,转换其中任意一个都可以

CAST完整代码示例如下::

SELECT A~* FROM VBFA AS A
INNER JOIN @LT_A AS B ON A~VBELV = B~KDAUF
AND CAST( RFMNG AS CURR( 23,3) ) = B~MSL
INTO TABLE @DATA(LT_VBFA1).

希望对大家有所帮助,后面我会补充更多的~