简体   繁体   English

如何用一个 ABAP SQL 语句连接以下 3 个表

[英]How to join the following 3 tables with exactly one ABAP SQL statement

I have the following 3 tables with data:我有以下 3 个包含数据的表:

ZMYTABLE with columns: ZUSER & ZTCODE and 2 records ZMYTABLE与列: ZUSERZTCODE和2条记录

elias  VA01  
elias  VF01

AGR_1251 with the records AGR_1251与记录

SD_role  VA01  
SD2_role VA01  
SD3_role VA01  
SD_role  VA02  
FI_role  VF01  
FI_role  VF02

AGR_USERS with records AGR_USERS有记录

elias  SD_role  
elias  SD2_role   
maria  SD_role  
maria  FI_role

I want to display the fields ZUSER , ZTCODE and AGR_NAME .我想显示字段ZUSERZTCODEAGR_NAME
I want all records from ZMYTABLE with the role in which exists each tcode for the specific user, namely:我希望来自ZMYTABLE所有记录ZMYTABLE具有特定用户的每个 tcode 存在的角色,即:

ZUSER---ZTCODE---AGRNAME  
elias---VA01-----SD_role  
elias---VA01-----SD2_role  
elias---VF01-----        

Can someone tell me how to do this by joining the 3 tables with exactly one ABAP SQL statement, in ABAP V7.01 sp07?有人能告诉我如何通过在 ABAP V7.01 sp07 中用一个 ABAP SQL 语句连接 3 个表来做到这一点吗?

I found it easier to use UNION , the first SELECT will return the lines which correspond to the transactions which match one of the user roles (elias, VA01, SD_role and SD2_role), and the second one will return the lines which correspond to the transactions which don't match any of the user roles (elias, VF01).我发现使用UNION更容易,第一个 SELECT 将返回与匹配一个用户角色(elias、VA01、SD_role 和 SD2_role)的事务对应的行,第二个将返回与事务对应的行与任何用户角色(elias、VF01)都不匹配。

I tested it by replacing ZMYTABLE with USR07.我通过用 USR07 替换 ZMYTABLE 来测试它。

    SELECT usr07~bname, usr07~tcode, agr_1251~agr_name
      FROM agr_users
      INNER JOIN usr07
        ON usr07~bname EQ agr_users~uname
      INNER JOIN agr_1251
        ON agr_1251~agr_name EQ agr_users~agr_name
           AND agr_1251~low  EQ usr07~tcode
    UNION
    SELECT DISTINCT usr07~bname, usr07~tcode, ' ' AS agr_name
      FROM usr07
      WHERE NOT EXISTS (
        SELECT * FROM agr_users
          INNER JOIN agr_1251
            ON agr_1251~agr_name EQ agr_users~agr_name
          WHERE usr07~bname  EQ agr_users~uname
            AND agr_1251~low EQ usr07~tcode )
    INTO TABLE @DATA(result).

It gives these results (formatted for ABAP Unit) :它给出了这些结果(格式化为 ABAP 单元):

    SORT result BY bname tcode agr_name.
    TYPES ty_result LIKE result.
    assert_equals( act = result exp = VALUE ty_result(
      ( bname = 'elias' tcode = 'VA01' agr_name = 'SD2_role' )
      ( bname = 'elias' tcode = 'VA01' agr_name = 'SD_role'  )
      ( bname = 'elias' tcode = 'VF01' agr_name = ''         ) ) ).    

Below is the ABAP Unit test code to demonstrate that it works, and you may play with it if needed.下面是 ABAP 单元测试代码来演示它的工作原理,如果需要,您可以使用它。 You need ABAP 7.52 (Open SQL Test Double Framework).您需要 ABAP 7.52(Open SQL Test Double Framework)。

CLASS ltc_main DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS
      INHERITING FROM cl_aunit_assert.
  PRIVATE SECTION.
    METHODS test FOR TESTING.
    CLASS-METHODS: class_setup, class_teardown.
    CLASS-DATA environment TYPE REF TO if_osql_test_environment.
ENDCLASS.
CLASS ltc_main IMPLEMENTATION.
  METHOD class_setup.
    environment = cl_osql_test_environment=>create( i_dependency_list = VALUE #( 
          ( 'USR07' ) ( 'AGR_1251' ) ( 'AGR_USERS' ) ) ).
  ENDMETHOD.
  METHOD test.
    TYPES ty_usr07 TYPE STANDARD TABLE OF usr07 WITH EMPTY KEY.
    TYPES ty_agr_1251 TYPE STANDARD TABLE OF agr_1251 WITH EMPTY KEY.
    TYPES ty_agr_users TYPE STANDARD TABLE OF agr_users WITH EMPTY KEY.

    environment->insert_test_data( EXPORTING i_data = VALUE ty_usr07(
      ( bname = 'elias' tcode = 'VA01' timestamp = 1 )
      ( bname = 'elias' tcode = 'VF01' timestamp = 2 ) ) ).
    environment->insert_test_data( EXPORTING i_data = VALUE ty_agr_1251(
      ( agr_name = 'SD_role'  low = 'VA01' counter = 1 )
      ( agr_name = 'SD2_role' low = 'VA01' counter = 1 )
      ( agr_name = 'SD3_role' low = 'VA01' counter = 1 )
      ( agr_name = 'SD_role ' low = 'VA02' counter = 2 )
      ( agr_name = 'FI_role ' low = 'VF01' counter = 1 )
      ( agr_name = 'FI_role ' low = 'VF02' counter = 2 ) ) ).
    environment->insert_test_data( EXPORTING i_data = VALUE ty_agr_users(
      ( uname = 'elias' agr_name = 'SD_role ' )
      ( uname = 'elias' agr_name = 'SD2_role' )
      ( uname = 'maria' agr_name = 'SD_role ' )
      ( uname = 'maria' agr_name = 'FI_role ' ) ) ).

    "<==== here insert the ABAP SQL provided above & expectations to verify

    ROLLBACK WORK.

  ENDMETHOD.

  METHOD class_teardown.
    environment->destroy( ).
  ENDMETHOD.

ENDCLASS.

If you have an ABAP release < 7.50, UNION is impossible, instead define 2 separate SELECT , the first one with INTO TABLE @DATA(result) and the second one with APPENDING TABLE result .如果您的 ABAP 版本 < 7.50,则UNION是不可能的,而是定义 2 个单独的SELECT ,第一个带有INTO TABLE @DATA(result) ,第二个带有APPENDING TABLE result


PS: I also did the following tests, inspired from the other answers, they don't work (most of them return the role "FI_role" for "VF01", instead of an empty role). PS:我还进行了以下测试,受到其他答案的启发,它们不起作用(其中大多数为“VF01”返回角色“FI_role”,而不是空角色)。

Failed attempt 1-A:失败的尝试 1-A:

     SELECT usr07~bname, usr07~tcode, agr_1251~agr_name
       FROM agr_users
       INNER JOIN usr07
         ON usr07~bname EQ agr_users~uname
       INNER JOIN agr_1251
         ON agr_1251~agr_name EQ agr_users~agr_name AND
            agr_1251~low      EQ usr07~tcode
       INTO TABLE @DATA(result).
    SORT result BY bname tcode agr_name.
    TYPES ty_result LIKE result.
    assert_equals( act = result exp = VALUE ty_result(
      ( bname = 'elias' tcode = 'VA01' agr_name = 'SD2_role' )
      ( bname = 'elias' tcode = 'VA01' agr_name = 'SD_role' ) ) ).

Failed attempt 1-B:失败的尝试 1-B:

     SELECT DISTINCT usr07~bname,
                 usr07~tcode,
                 agr_1251~agr_name
           FROM usr07
           INNER JOIN agr_1251
             ON agr_1251~low EQ usr07~tcode
           INNER JOIN agr_users
             ON agr_users~uname EQ usr07~bname
           WHERE
              agr_users~agr_name EQ agr_1251~agr_name OR EXISTS (
              SELECT *
              FROM agr_users AS inner_agr_users
              INNER JOIN agr_1251 AS inner_agr_1251
                ON inner_agr_1251~agr_name EQ inner_agr_users~agr_name
              WHERE
                inner_agr_users~agr_name EQ agr_1251~agr_name
           )
           INTO TABLE @DATA(result).
    SORT result BY bname tcode agr_name.
    TYPES ty_result LIKE result.
    assert_equals( act = result exp = VALUE ty_result(
      ( bname = 'elias' tcode = 'VA01' agr_name = 'SD2_role' )
      ( bname = 'elias' tcode = 'VA01' agr_name = 'SD_role' )
      ( bname = 'elias' tcode = 'VF01' agr_name = 'FI_role' ) ) ).

Failed attempt 2:失败的尝试 2:

     SELECT b~bname, b~tcode, a~agr_name
       FROM agr_1251 as a
       INNER JOIN usr07 as b
         ON a~low EQ b~tcode
       INNER JOIN agr_users as c
         ON a~agr_name EQ c~agr_name
       INTO TABLE @DATA(result).
    SORT result BY bname tcode agr_name.
    TYPES ty_result LIKE result.
    assert_equals( act = result exp = VALUE ty_result(
      ( bname = 'elias' tcode = 'VA01' agr_name = 'SD2_role' )
      ( bname = 'elias' tcode = 'VA01' agr_name = 'SD_role' )
      ( bname = 'elias' tcode = 'VA01' agr_name = 'SD_role' )
      ( bname = 'elias' tcode = 'VF01' agr_name = 'FI_role' ) ) ).

DB access should look like this:数据库访问应如下所示:

SELECT DISTINCT zmytable~zuser,
                zmytable~ztcode,
                agr_1251~agr_name
FROM zmytable
INNER JOIN agr_1251
  ON agr_1251.ztcode EQ zmytable.ztcode
INNER JOIN agr_users
  ON agr_users.zuser EQ zmytable.zuser
WHERE
   agr_users.agr_name EQ agr_1251.agr_name OR EXISTS(
   SELECT *
   FROM agr_users AS inner_agr_users
   INNER JOIN agr_1251 AS inner_agr_1251
     ON inner_agr_1251.agr_name EQ inner_agr_users.agr_name
   WHERE
     inner_agr_users.agr_name EQ agr_1251.agr_name
).

Add INTO clause and deal with the output.添加INTO子句并处理输出。

  • I am planning to upgrade the answer with explanations when I have time.我打算在有时间的时候用解释来升级答案。

To access all records, you should use DB Access as below.要访问所有记录,您应该使用 DB Access,如下所示。

SELECT b~zuser, b~ztcode, a~agr_name
  FROM agr_1251 as a
  INNER JOIN zmytable as b
    ON a~tcode EQ b~tcode
  INNER JOIN agr_user as c
    ON a~agr_name EQ c~agr_name.

Rest you can use ABAP to display output.休息一下,您可以使用 ABAP 来显示输出。

Triple Join works for version > 7.4. Triple Join适用于版本 > 7.4。

SELECT c~zuser, a~zrole, c~ztcode INTO CORRESPONDING FIELDS OF TABLE @lt_result
     FROM agr_users AS a INNER JOIN agr_1251 AS b 
         ON a~zrole = b~zrole
            RIGHT OUTER JOIN zmytable AS c 
              ON c~ztcode = b~ztcode AND c~zuser = a~zuser.

I have been looking in which table the SU53 report contents is stored. 我一直在寻找SU53报告内容存储在哪个表中。 It seems it's stored in USR07 and USR07_EXT for higher releases. 似乎它存储在USR07和USR07_EXT中以获取更高版本。

This is how I got to this post. 这就是我到达这篇文章的方式。

However, this table is always empty ALTHOUGH there is clearly SU53 content for a different userID than mine. 但是,该表始终为空,尽管对于其他用户ID和我的用户ID显然有SU53内容。

Really scratching my head here, because if you hit F1 in the SU53 report and then the wrench icon, it points to table USR07, which is then empty. 在这里真的很伤人,因为如果您在SU53报告中单击F1然后单击扳手图标,它将指向表USR07,该表为空。

What am I missing ? 我想念什么? Thanks 谢谢

Oh by the way, I am looking for a table that retains the last auth check fail per user. 哦,顺便说一句,我正在寻找一个表,该表保留每个用户的最后一次身份验证检查失败。 We want to use this info so a chatbot can grab this info and cross-reference with UST12 and ultimately the originating single role. 我们希望使用此信息,以便聊天机器人可以获取此信息并与UST12以及最终与原始单个角色进行交叉引用。 We have a setup where each auth-object-field-value combination is included in exactly 1 single role. 我们有一个设置,其中每个auth-object-field-value组合都恰好包含1个单一角色。 Otherwise, the chatbot would have to present a list of multiple single role matches to the end-user, of whom we know he/she will pick any role. 否则,聊天机器人将必须向最终用户提供多个单个角色匹配的列表,我们知道最终用户将选择该角色。 So, having only 1 match, the chatbot can do it's single role requesting work on behalf of that user. 因此,只有1个匹配项,聊天机器人就可以代表该用户来完成请求任务的单一角色。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM