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).
I tested it by replacing ZMYTABLE with USR07.
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) :
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. You need 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
.
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).
Failed attempt 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:
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:
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' ) ) ).