Left join on 2 tables in ABAP 7.02 - abap

I want to join 4 tables T001, KNKK, KNB1 and KNA1, to get all customers from KNB1/KNA1 and their Risk Category in KNKK.
We need a left join from KNKK but the join condition is based on 2 tables: the T001-KKBER and KNA1-KUNNR.
But I get the syntax error:
Unable to compare with "T001~KKBER". A table can be joined with a maximum of one other table using LEFT OUTER JOIN.
The select is:
SELECT knb1~kunnr kna1~name1 kna1~lifnr knb1~akont
INTO TABLE git_kunnr_tab
FROM kna1
INNER JOIN knb1
ON kna1~kunnr EQ knb1~kunnr
INNER JOIN t001
ON knb1~bukrs EQ t001~bukrs
LEFT JOIN knkk
ON knb1~kunnr EQ knkk~kunnr AND
t001~kkber EQ knkk~kkber
WHERE knb1~kunnr IN s_kunnr
AND knb1~bukrs = p_bukrs.
Our system is old ECC6 7.02 so we cannot implement the new features of ABAP.
Is there any way to do it in 1 select?

Not sure, what error you get, but this is syntactically correct:
SELECT ...
INTO TABLE ...
FROM kna1
INNER JOIN knb1
ON kna1~kunnr EQ knb1~kunnr
INNER JOIN t001
ON knb1~bukrs EQ t001~bukrs
LEFT JOIN knkk
ON knb1~kunnr EQ knkk~kunnr AND
t001~kkber EQ knkk~kkber
WHERE ...

I believe that there is no way to do a join with all these tables and select ALL customers from KNA1 even if they do not exist in KNKK.
Maybe there is a way with SubQuery but I cannot think sth now.
So I made 2 selects and fill 2 ITABs and then I loop into the one with KUNNR & CTLPC and modify the 2nd by passing the CTLPC value. So the code is now:
select knb1~kunnr kna1~name1 kna1~lifnr knb1~akont
knb1~fdgrv knb1~frgrp
into table git_kunnr_tab
from knb1 as knb1 left join kna1 as kna1
on knb1~kunnr = kna1~kunnr
where knb1~kunnr in s_kunnr
and knb1~bukrs = p_bukrs.
select knkk~kunnr knkk~ctlpc into table lit_kunnr_risk
from knkk as knkk inner join t001 as t001
on knkk~kkber = t001~kkber
where t001~bukrs = p_bukrs and
knkk~ctlpc <> ''.
sort git_kunnr_tab by kunnr.
loop at lit_kunnr_risk into lwa_kunnr_risk.
gwa_kunnr_tab-ctlpc = lwa_kunnr_risk-ctlpc.
modify git_kunnr_tab from gwa_kunnr_tab transporting ctlpc
where kunnr = lwa_kunnr_risk-kunnr.
clear gwa_kunnr_tab.
endloop.
If there is a better way to do this, please post it.

Related

SQL Query from "Triangular Relation" of Tables

I am having a hard time to get a - seemingly simple - right in SQL. I am using MS Access but I guess it doesn't really matter here.
My data structure looks like this:
So tblA has the "Products", tblB the "Components" and tblC the "Modules". It's just an example obviously.
tblA ("Product") has m:n relation to tblB ("Component"), i.e. a product consists of some components and components can belong to many products. tblB ("Component") has m:n relation to tblC ("Modules"), i.e. a component consists of modules and modules can belong to many components. Now the twist is, that I also have a m:n relation between tblA and tblC, i.e. a mapping of products and modules. This is due to the fact that the "configuration" of a component can be different depending on the product for which is it. So for "Product 1" "Component 2" needs to consist of "Module 1" and "Module 2" while for "Product 2" "Component 2" is just "Module 2".
I want a query with a result like this
|Product|Component|Module|
|-------|---------|------|
|Prod1 |C1 | |
|Prod1 |C2 | |
|Prod1 |C2 |M1 |
|Prod1 |C2 |M2 |
|Prod2 |C2 | |
|Prod2 |C2 |M2 |
|Prod2 |C3 | |
|Prod2 |C3 |M3 |
where I have "Prod1" and "Prod2" in tblA; "C1", "C2", "C3" in tblB and "M1","M2","M3" in tblC. Relations are
So essentially I want a table with Product, Component, Module that holds all the combinations Product+
Now with a SQL Query
SELECT tblA.Product,
tblB.Component,
tblC.Module
FROM tblC
INNER JOIN ((tblA
INNER JOIN (tblB
INNER JOIN mapAB ON tblB.[Component] = mapAB.[Component]) ON tblA.[Product] = mapAB.[Product])
INNER JOIN mapAC ON tblA.Product = mapAC.Product) ON tblC.Module = mapAC.Module;
I get
which is understandable but not what I want. I have tried to do first a join of tblA and tblB and to combine this with a LEFT JOIN (or RIGHT JOIN) with a join of tblB and tblC but this gives "unsupported join operation" errors.
Any ideas on how to approach this problem?
Looking at your relationships, you haven't used your primary keys to make the one to many relationships, but the data fields.
In this case, this query should work for you:
SELECT tblA.Product, mapAC.Module, MapAB.Component
FROM (tblA LEFT JOIN mapAC ON tblA.Product = mapAC.Product) LEFT JOIN MapAB ON tblA.Product = MapAB.Product;
All the other tables are in this case just informative since you already have the data available in the tables MapAB and MapAC.
I would advise using the primary keys in your relationships.
Update:
Your query can follow three routes to get the data you need:
tblA -> mapAB + mapAC
tblA -> mapAB -> tblB -> mapBC -> tblC
tblA -> mapAC -> tblC -> mapBC -> tblB
Depending on which data route you want to follow your query will look differently.
Route 2 Query:
SELECT tblA.Product, MapAB.Component, mapBC.Module
FROM (((tblA LEFT JOIN MapAB ON tblA.Product = MapAB.Product) LEFT JOIN tblB ON MapAB.Component = tblB.Component) LEFT JOIN mapBC ON tblB.Component = mapBC.Component) LEFT JOIN tblC ON mapBC.Module = tblC.Module;
Route 3 Query:
SELECT tblA.Product, mapAC.Module, mapBC.Component
FROM (((tblA LEFT JOIN mapAC ON tblA.Product = mapAC.Product) LEFT JOIN tblC ON mapAC.Module = tblC.Module) LEFT JOIN mapBC ON tblC.Module = mapBC.Module) LEFT JOIN tblB ON mapBC.Component = tblB.Component;
Ok, based on jbud suggestions I was able to build up the desired result like this:
qryProdModComp = SELECT tblA.Product, mapBC.Component, mapAC.Module
FROM (tblA LEFT JOIN mapAC ON tblA.Product = mapAC.Product) LEFT JOIN mapBC ON mapAC.Module = mapBC.Module;
already almost gives what I want
Notice however, that the line with Prod1 and C1 is missing (for which no Mx is directly linked).
To get this I added
qrySingleC = SELECT tblB.Component AS Component
FROM tblB
LEFT JOIN mapBC
ON tblB.Component = mapBC.Component
WHERE mapBC.Component Is Null
UNION
SELECT mapBC.Component
FROM tblB
RIGHT JOIN mapBC
ON tblB.Component = mapBC.Component
WHERE tblB.Component Is Null
qryProdCompOnly = SELECT tblA.Product, mapAB.Component, NULL AS Module
FROM tblA INNER JOIN ( qrySingleC INNER JOIN mapAB ON qrySingleC.Component = mapAB.Component ) ON tblA.Product = mapAB.Product;
qryOverall = SELECT Product,Component,Module FROM qryProdCompMod UNION SELECT Product,Component,Module FROM qryProdCompOnly;
which gives
Getting to the exact same result as requested in my original post actually looks still a bit cleaner
qryProdCompOnly2 = SELECT tblA.Product, mapAB.Component, NULL AS Module
FROM tblA INNER JOIN mapAB ON tblA.Product = mapAB.Product;
qryOverall = SELECT Product,Component,Module FROM qryProdCompMod UNION SELECT Product,Component,Module FROM qryProdCompOnly2;
gives

Records are not selected from EQUI

I am currently working on an application which requires all equipments from the EQUI table. When I look at the table via SE11, there are 225 entries.
When I try to select the equipments through a function module, I get a very different result.
SELECT E~EQUNR, E~EQART, I~BEBER, Q~IWERK, I~TPLNR, K~EQKTX, K~SPRAS, E~GERNR, X~PLTXT
FROM EQUI AS E
INNER JOIN EQKT AS K ON K~EQUNR EQ E~EQUNR
INNER JOIN EQUZ AS Q ON Q~EQUNR EQ E~EQUNR
INNER JOIN ILOA AS I ON I~ILOAN EQ Q~ILOAN
INNER JOIN IFLOTX AS X on X~TPLNR EQ I~TPLNR
WHERE E~EQUNR LIKE #P_EQUNR
AND I~BEBER LIKE #P_BEBER
AND I~TPLNR LIKE #P_TPLNR
AND Q~IWERK LIKE #P_IWERK
AND E~GERNR LIKE #P_GERNR
AND K~SPRAS EQ #IV_SPRAS
AND X~SPRAS EQ #IV_SPRAS
INTO TABLE #ET_EQUIPS.
When I query them with this select statement, I do get the same amount of results as the EQUI table, but without the other data I require.
SELECT E~EQUNR, E~EQART
FROM EQUI AS E
INNER JOIN JEST AS J ON J~OBJNR EQ E~OBJNR
INNER JOIN TJ02T AS T on T~ISTAT EQ J~STAT
WHERE INACT NE 'X'
AND J~STAT NE 'I0320'
AND J~STAT NE 'I0076'
INTO TABLE #ET_EQUIPS.
Any help on how to get the same amount of results with all the other data as well?
Typically it happens when some of your conditions are not met or the recordset is not presented in one of the joined tables. Try to use LEFT OUTER JOIN and check all your WHERE conditions one by one.
You can start with the following statement:
SELECT E~EQUNR, E~EQART, I~BEBER, Q~IWERK, I~TPLNR, K~EQKTX, K~SPRAS, E~GERNR, X~PLTXT
FROM EQUI AS E
LEFT OUTER JOIN EQKT AS K ON K~EQUNR EQ E~EQUNR
LEFT OUTER JOIN EQUZ AS Q ON Q~EQUNR EQ E~EQUNR
LEFT OUTER JOIN ILOA AS I ON I~ILOAN EQ Q~ILOAN
LEFT OUTER JOIN IFLOTX AS X on X~TPLNR EQ I~TPLNR

SQL - how to correctly implement LEFT Join with Inner Joins

I have two tables of information. One is present in the system and another is being imported to compare and update the information. I am trying to use a Right Join to get the information that is in Table B that is NOT in Table A. I need to introduct the info from Table B so the output values are not NULL.
FULL CODE:
Select TDS, TL, IK
From (Select ENT_LINK_OBJECTS.OBJ_NAME As TDS, ENT_ITEM_MASTER.ITEM_CODE As TL, ENT_ITEM_MASTER.ITEM_KEY As IK
From ENT_LINK_OBJECTS
Inner Join ENT_ITEM_MASTER
On ENT_ITEM_MASTER.ITEM_KEY=ENT_LINK_OBJECTS.ENTITY_KEY) As A
RIGHT JOIN Sheet1 B
On A.TDS=B.TOOLING_DATA_SHEET
Where A.TDS is Null
Example:
Table A
From code:
Select ENT_LINK_OBJECTS.OBJ_NAME, ENT_ITEM_MASTER.ITEM_CODE, ENT_ITEM_MASTER.ITEM_KEY
From ENT_LINK_OBJECTS
Inner Join ENT_ITEM_MASTER
On ENT_ITEM_MASTER.ITEM_KEY=ENT_LINK_OBJECTS.ENTITY_KEY
Should produce:
OBJ_NAME ITEM_CODE IK
tds-123 tl-1234 387
tds-456 tl-8721 879
tds-983 tl-1987 928
Table B
With code:
Select Sheet1.TOOLING_DATA_SHEET, Sheet1.CUTTING_TOOL, ENT_ITEM_MASTER.ITEM_KEY
From Sheet1
Inner Join ENT_ITEM_MASTER
On ENT_ITEM_MASTER.ITEM_CODE=Sheet1.CUTTING_TOOL
Should produce:
TOOLING_DATA_SHEET CUTTING_TOOL ITEM_KEY
tds-123 tl-1234 387
tds-456 tl-8721 879
tds-983 tl-1987 928
tds-873 tl-9873 827
tds-982 tl-9872 287
What code currently gives back:
TDS TL IK
NULL NULL NULL
NULL NULL NULL
What the code should give back:
TDS TL IK
tds-873 tl-9873 827
tds-982 tl-9872 287
EDIT ATTEMPT AT LEFT JOIN - not working, join for Sheet1 needs to be implemented
Select l.OBJ_NAME As TDS, i.ITEM_CODE As TL, i.ITEM_KEY As IK
From ENT_LINK_OBJECTS l
Join ENT_ITEM_MASTER i On i.ITEM_KEY=l.ENTITY_KEY
Left Join Sheet1 s on l.OBJ_NAME = s.TOOLING_DATA_SHEET and
i.ITEM_CODE = s.CUTTING_TOOL and
i.ITEM_KEY = i.ITEM_KEY
where s.CUTTING_TOOL is null
You can use left join/is null:
select l.OBJ_NAME As TDS
, i.ITEM_CODE As TL
, i.ITEM_KEY As IK
from ENT_LINK_OBJECTS l
join ENT_ITEM_MASTER i on i.ITEM_KEY = l.ENTITY_KEY
left Join Sheet1 s on l.OBJ_NAME = s.TOOLING_DATA_SHEET and
i.ITEM_CODE = s.CUTTING_TOOL and
i.ITEM_KEY = s.ITEM_KEY
where s.CUTTING_TOOL is null
try this query
select a.* from tableb a
right join tablea b on a.tooling_data_sheet=b.obj_name
where b.obj_name is null
You might also consider simply using not exists:
select lo.*
From ENT_LINK_OBJECTS lo
where not exists (select 1
from ENT_ITEM_MASTER im
where im.ITEM_KEY = lo.ENTITY_KEY
);
The abbreviations lo and im are called table aliases. Using them is a good idea. Sometimes they are needed; more often they just make a query easier to write and to read. It is considered a best practice to use abbreviations of the table names for them.
SOLUTION: When using Left Join with multiple Inner Join Statements, you can define as follows
Select TDS, TL, IK
From (Select Sheet1.TOOLING_DATA_SHEET As TDS, Sheet1.CUTTING_TOOL As TL, ENT_ITEM_MASTER.ITEM_KEY As IK
From Sheet1
Inner Join ENT_ITEM_MASTER
On ENT_ITEM_MASTER.ITEM_CODE=Sheet1.CUTTING_TOOL) As A
Left Join (Select ENT_LINK_OBJECTS.OBJ_NAME, ENT_ITEM_MASTER.ITEM_CODE, ENT_ITEM_MASTER.ITEM_KEY
From ENT_LINK_OBJECTS
Inner Join ENT_ITEM_MASTER
On ENT_ITEM_MASTER.ITEM_KEY=ENT_LINK_OBJECTS.ENTITY_KEY) As B
On A.TDS=B.OBJ_NAME
Where B.OBJ_NAME is Null

Not able to LEFT OUTER JOIN three tables

I've got a problem.
Currently I have three tables, the first table is the main table and if there is no record in the second table, write it too. But if a record exists in the second table, so from the third table display "dispo" information..
I want to use three SAP table - lagp, lqua and marc.
Me goal is write all stock positions from lagp.
2x LEFT JOIN doesnt work: "Unable to compare with"B~MATNR". A table can be joined with a maximum of one other table usign LEFT OUTER JOIN.
Structure:
TYPES:
BEGIN OF t_work,
lgnum TYPE lgnum,
lgtyp TYPE lgtyp,
lgpla TYPE lgpla,
bdatu TYPE lagp_bdatu,
matnr TYPE matnr,
verme TYPE lqua_verme,
meins TYPE meins,
dispo TYPE dispo,
END OF t_work.
DATA:
lt_work TYPE TABLE OF t_work INITIAL SIZE 0,
ls_work LIKE LINE OF lt_work.
And SQL command:
SELECT a~lgnum a~lgtyp a~lgpla a~bdatu b~matnr b~verme b~meins c~dispo FROM lagp AS a
LEFT JOIN lqua AS b ON a~lgnum = b~lgnum AND a~lgtyp = b~lgtyp AND a~lgpla = b~lgpla
INNER JOIN marc AS c ON b~matnr = c~matnr AND b~werks = c~werks
INTO TABLE lt_work
WHERE a~lgnum IN so_lgnum
AND a~lgtyp IN so_lgtyp
AND a~skzua EQ space
AND a~skzue EQ space.
But as result is only one stock position - http://i.stack.imgur.com/1sEEo.png
Can you tell me, how the SQL code has look?
Thank you
Try:
SELECT a~lgnum, a~lgtyp, a~lgpla, a~bdatu, b~matnr, b~verme, b~meins, c~dispo
FROM lagp AS a
LEFT JOIN ( lqua AS b
JOIN marc AS c ON b~matnr = c~matnr AND b~werks = c~werks )
ON a~lgnum = b~lgnum AND a~lgtyp = b~lgtyp AND a~lgpla = b~lgpla
INTO TABLE #lt_work
WHERE a~lgnum IN #so_lgnum
AND a~lgtyp IN #so_lgtyp
AND a~skzua EQ #space
AND a~skzue EQ #space.
Other option would be to put the join between LQUA and MARC in a view and do an outer join with the view. Or split out the select on MARC and do that while looping at the data found with a select on LAGP and LQUA.
I got that fine working code:
SELECT ma~matnr ma~mtart ma~ernam ma~ersda ma~laeda
de~maktx as maktx_de fr~maktx as maktx_fr it~maktx as maktx_it
FROM mara as ma
LEFT JOIN MAKT as de ON de~matnr = ma~matnr AND de~spras = 'DE'
LEFT JOIN MAKT as fr ON fr~matnr = ma~matnr AND fr~spras = 'FR'
LEFT JOIN MAKT as it ON it~matnr = ma~matnr AND it~spras = 'IT'
INTO CORRESPONDING FIELDS OF TABLE g_it_material
WHERE ma~ernam IN so_ERNAM
AND ma~laeda IN so_LAEDA
AND ma~matnr IN so_MATNR.
and it works fine. What did you say about multi-leftjoins?

SQL SELECT from third level table

Ok I know little about SQL so bear with me...
I'm trying to see if certain values exist in a third level table and I don't know how to go about it. Here is the scenario...
I have a Accident table that holds accident information. It has 3 one-to-many child tables (Units, Occupants, NonMotorists). An each of those child tables have their own many-to-many child table (Alcohol). I need to be able to have some way of seeing if a range of values exists in a field in those Alcohol tables. Here is watered down version of what my structure for the tables looks like...
--tblAccident--_
PK_AccidentNumber
--tblAccidentUnit--
PK_PrimaryKey
FK_AccidentNumber
--tblAccidentOccupant--
PK_PrimaryKey
FK_AccidentNumber
--tblAccidentNonMotorist--
PK_PrimaryKey
FK_AccidentNumber
--tblAccidentUnitAlcohol--
PK_PrimaryKey
FK_ForeignKey
AlcoholValue <---- THIS IS WHAT I NEED TO SEARCH
--tblAccidentOccupantAlcohol--
PK_PrimaryKey
FK_ForeignKey
AlcoholValue <---- THIS IS WHAT I NEED TO SEARCH
--tblAccidentNonMotoristAlcohol--
PK_PrimaryKey
FK_ForeignKey
AlcoholValue <---- THIS IS WHAT I NEED TO SEARCH
I hope this makes some sense as to what i am trying to accomplish. thank you
I assume you just want to get info from the third level table if the range exists.
Try the query given below:
Since the database is not specified am not sure if the BETWEEN operator in your database would includes the test values.
SELECT AccidentNumber, 'AccidentUnit' AS TableFound, c.PrimaryKey AS TableKeyValue
FROM tblAccident a INNER JOIN tblAccidentUnit b
ON a.AccidentNumber = b.AccidentNumber INNER JOIN tblAccidentUnitAlcohol c
ON b.PrimaryKey = c.ForeignKey
AND c.AlcoholValue BETWEEN <RANGE_START> AND <RANGE_END>
UNION
SELECT AccidentNumber, 'AccidentOccupant' AS TableFound, c.PrimaryKey AS TableKeyValue
FROM tblAccident a INNER JOIN tblAccidentOccupant b
ON a.AccidentNumber = b.AccidentNumber INNER JOIN tblAccidentOccupantAlcohol c
ON b.PrimaryKey = c.ForeignKey
AND c.AlcoholValue BETWEEN <RANGE_START> AND <RANGE_END>
UNION
SELECT AccidentNumber, 'AccidentNonMotorist' AS TableFound, c.PrimaryKey AS TableKeyValue
FROM tblAccident a INNER JOIN tblAccidentNonMotorist b
ON a.AccidentNumber = b.AccidentNumber INNER JOIN tblAccidentNonMotoristAlcohol c
ON b.PrimaryKey = c.ForeignKey
AND c.AlcoholValue BETWEEN <RANGE_START> AND <RANGE_END>