Find materials by bill of material - abap

I have a stlnr and a stlal and I want to find all materials in a bill of material using these two fields. I have no idea how to do that, so please help :)

the tables you need to look at are STKO (header), STAS (position selection) and STPO (positions). You need to know the type of BOM, which is in field STKO~STLTY. Using the type and your STLNR you can get the header row from table STKO. The STKO entry is connected to STAS using STLTY, STLNR and STLAL. Table STPO contains the actual BOM positions and is connected to STAS using STLTY, STLNR and STLKN (which is in STAS but not in STKO, which is why you need table STAS too).
You also may need to look at table STPU which is connected to STPO and contains subelements within a BOM position. In our system STPU is completly empty but that may not be the case in yours.

You can call the FM CABM_READ_BOM_ITEM, you will need the following:
CALL FUNCTION 'CABM_READ_BOM_ITEM'
EXPORTING
i_stlty = i_stlty
i_stlnr = i_stlnr
i_stlal = i_stlal
i_date_from = i_date_from
* I_DATE_TO = I_DATE_TO
* I_WERKS = I_WERKS
TABLES
exp_bom_item = exp_bom_item
* EXCEPTIONS
* NO_RECORD_FOUND = 1
Which means you will need STLTY, as it is part of the key of STKO.

Related

How to get CJ20N project hierarchy?

I need to get the hierarchy of a project (like shown in transaction CJ20N) in ABAP.
I've found a function module 'GET_PROJECT_HIERARCHY', which delivers me a table like this:
However, I rather need all WBS elements, order numbers, purchase requests and network elements (AUFNR) in this project. Is there a better function module or a next step to the GET_PROJECT_HIERARCHY?
At least what concerns WBS elements you can get them from table PRPS
DATA: lt_prhi TYPE TABLE OF prhi.
CALL FUNCTION 'GET_PROJECT_HIERARCHY'
EXPORTING
i_pronr = '00000113'
TABLES
t_prhi = lt_prhi.
SELECT * FROM prps
INTO TABLE #DATA(lt_prps)
FOR ALL ENTRIES IN lt_prhi
WHERE pspnr = lt_prhi-posnr.
cl_demo_output=>display( lt_prps ).
Thank you Suncatcher, your directed me the right way with the PRPS table and I'll accept your answer.
I finally decided to build a custom query, looking in the tables PRPS, AFVC, AUFK, AFKO and PROJ to get all the data I want using the PSPHI column from GET_PROJECT_HIERARCHY.
I just wanted to post my solution, maybe it helps others too.
SELECT
PROJ~PSPID,
PROJ~POST1 AS PROJ_NAME,
PRPS~POST1 AS WSB_NAME,
AFVC~LTXA1,
AUFK~KTEXT
FROM
PRPS
LEFT JOIN PROJ ON PROJ~PSPNR = PRPS~PSPHI
LEFT JOIN AUFK ON AUFK~PSPEL = PRPS~PSPNR
LEFT JOIN AFKO ON AUFK~AUFNR = AFKO~AUFNR
LEFT JOIN AFVC ON AFKO~AUFPL = AFVC~AUFPL
WHERE
PRPS~PSPHI = '00000136'
INTO TABLE #DATA(LT_RESULT)

Multiple entries in crystal reportviewer after adding a SQL expression field

I am using Visual Studio 2017 and I installed the latest crystal reportviewer (22)
What I want is to click a button and create a report from the customer that is selected in the datagridview and the addresses that are shown in the second datagridview.
I managed to do all that but the problem is that a few fields contain numbers which need to be converted to text. An SQL query I would use to do this would be like:
SELECT c.customer_nr, c.status, s.rename FROM CUSTOMERS c INNER JOIN SETUP s on s.id = c.status WHERE s.afk = 'STA'
In my SETUP database I have the columns ID,AFK and RENAME so if the status would be 1 it would convert to text: "ACTIVE", if status = 2 it would convert to "INACTIVE" for example.
I could do something with a formula field like this:
IF ({c.status} = 1) THEN "ACTIVE" ELSE
IF ({c.status}) = 2 THEN "INACTIVE"
but that is not good because i could add another status or change the name in the database etc.
So then I tried with an SQL expression field and I put something like this:
(
SELECT "SETUP"."RENAME" FROM SETUP
WHERE "SETUP"."AFK" = 'STA' AND "SETUP"."ID" = "CUSTOMERS"."STATUS"
)
There must be something wrong because I get the correct conversion but there is only one address in the database but I get 7 pages all with the same address. There should only be one address like I get when I remove the SQL expression field. Where does it go wrong?
* EDIT *
I found the problem. When I create a new database that contains only unique id's then it works. In my original database I have multiple times the id's 1,2,3,4,5 but with different abbreviations in column AFK. Somehow the query looks for the id value and every time it finds this id no matter the AFK value it generates an entry for the address value.
Maybe in the future I will find out how this exactly works for now I have a workaround.
Create a new table for example CrRepSta and add the following entries:
ID,AFK,RENAME
1,STA,Active
2,STA,Inactive
etc
The new query:
(
SELECT "CrRepSta"."RENAME" FROM CrRepSta
WHERE "CrRepSta"."AFK" = 'STA' AND "CrRepSta"."ID" = "CUSTOMERS"."STATUS"
)
And by the way the statement "CrRepSta"."AFK" = 'STA' is not really needed.

MS Access-Return Record Below Current Record

I am very new to Access, and what I am trying to do seems like it should be very simple, but I can't seem to get it.
I am a structural engineer by trade and am making a database to design buildings.
My Diaphragm Analysis Table includes the fields "Floor_Name", "Story_Number", "Wall_Left", and "Wall_Right". I want to write a new query that looks in another query called "Shear_Wall_incremental_Deflection" and pulls information from it based on input from Diaphragm Analysis. I want to take the value in "Wall_Right" (SW01), find the corresponding value in "Shear_Wall_incremental_Deflection", and report the "Elastic_Deflection" corresponding to the "Story_Below" instead of the "Story_Number" in the Diaphragm Analysis Table. In the case where "Story_Number" = 1, "Story_Below" will be 0 and I want the output to be 0.
Same procedure for "Wall_Left", but I'm just taking it one step at a time.
It seems that I need to use a "DLookup" in the expression builder with TWO criteria, one that Wall_Right = Shear_Wall and one that Story_Number = Story_Below, but when I try this I just get errors.
"Shear_Wall_incremental_Deflection" includes shearwalls for all three stories, i.e. it starts at SW01 and goes through SWW for Story Number 3 and then starts again at SW01 for Story Number 2, and so on until Story Number 1. I only show a part of the query results in the image, but rest assured, there are "Elastic_Deflection" values for story numbers below 3.
Here is my attempt in the Expression Builder:
Right_Defl_in: IIf(IsNull([Diaphragm_Analysis]![Wall_Right]),0,DLookUp("[Elastic_Deflection_in]","[Shear_Wall_incremental_Deflection]","[Shear_Wall_incremental_Deflection]![Story_Below]=" & [Diaphragm_Analysis]![Story_Number]))
I know my join from Diaphragm_Analysis "Wall_Left" and "Wall_Right" must include all records from Diaphragm_Analysis and only those from "Shear_Wall_incremental_Deflection"![Shear_Walls] where the joined fields are equal, but that's about all I know.
Please let me know if I need to include more information or send out the database file.
Thanks for your help.
Diaphragm Analysis (Input Table)
Shear_Wall_incremental_Deflection (Partial Image of Query)
I think what you are missing is that you can and should join to Diaphragm_Analysis twice, first time to get the Story_Below value and second to use it to get the corresponding Elastic_Deflection value.
To handle the special case where Story_Below is zero, I would write a separate query (only requires one join this time) and 'OR together' the two queries using the UNION set operation (note the following SQL is untested):
SELECT swid.Floor_Name,
swid.Story_Number,
swid.Wall_Left,
da2.Elastic_Deflection AS Story_Below_Elastic_Deflection
FROM ( Shear_Wall_incremental_Deflection swid
INNER JOIN Diaphragm_Analysis da1
ON da1.ShearWall = swid.Wall_Left )
INNER JOIN Diaphragm_Analysis da2
ON da2.ShearWall = swid.Wall_Left
AND da2.Story_Number = da1.Story_Below
UNION
SELECT swid.Floor_Name,
swid.Story_Number,
swid.Wall_Left,
0 AS Story_Below_Elastic_Deflection
FROM Shear_Wall_incremental_Deflection swid
INNER JOIN Diaphragm_Analysis da1
ON da1.ShearWall = swid.Wall_Left
WHERE da1.Story_Below = 0;
I've assumed that there is no data where Story_Number is zero.

Selecting rows from Parent Table only if multiple rows in Child Table match

Im building a code that learns tic tac toe, by saving info in a database.
I have two tables, Games(ID,Winner) and Turns(ID,Turn,GameID,Place,Shape).
I want to find parent by multiple child infos.
For Example:
SELECT GameID FROM Turns WHERE
GameID IN (WHEN Turn = 1 THEN Place = 1) AND GameID IN (WHEN Turn = 2 THEN Place = 4);
Is something like this possible?
Im using ms-access.
Turm - Game turn GameID - Game ID Place - Place on matrix
1=top right, 9=bottom left Shape - X or circle
Thanks in advance
This very simple query will do the trick in a single scan, and doesn't require you to violate First Normal Form by storing multiple values in a string (shudder).
SELECT T.GameID
FROM Turns AS T
WHERE
(T.Turn = 1 AND T.Place = 1)
OR (T.Turn = 2 AND T.Place = 4)
GROUP BY T.GameID
HAVING Count(*) = 2;
There is no need to join to determine this information, as is suggested by other answers.
Please use proper database design principles in your database, and don't violate First Normal Form by storing multiple values together in a single string!
The general solution to your problem can be accomplished by using a sub-query that contains a self-join between two instances of the Turns table:
SELECT * FROM Games
WHERE GameID IN
(
SELECT Turns1.GameID
FROM Turns AS Turns1
INNER JOIN Turns AS Turns2
ON Turns1.GameID = Turns2.GameID
WHERE (
(Turns1.Turn=1 AND Turns1.Place = 1)
AND
(Turns2.Turn=2 AND Turns2.Place = 4))
);
The Self Join between Turns (aliased Turns1 and Turns2) is key, because if you just try to apply both sets of conditions at once like this:
WHERE (
(Turns.Turn=1 AND Turns.Place = 1)
AND
(Turns.Turn=2 AND Turns.Place = 4))
you will never get any rows back. This is because in your table there is no way for an individual row to satisfy both conditions at the same time.
My experience using Access is that to do a complex query like this you have to use the SQL View and type the query in on your own, rather than use the Query Designer. It may be possible to do in the Designer, but it's always been far easier for me to write the code myself.
select GameID from Games g where exists (select * from turns t where
t.gameid = g.gameId and ((turn =1 and place = 1) or (turn =2 and place =5)))
This will select all the games that have atleast one turn with the coresponding criteria.
More info on exist:
http://www.techonthenet.com/sql/exists.php
I bypassed this problem by adding a column which holds the turns as a string example : "154728" and i search for it instead. I think this solution is also less demanding on the database

how to i remove characheters from the prefix table and make sure only from the start of string are removed

I need to be able to strip the following prefixes from product codes as you see I have included a simple query while yes the below shows me the cm im not wanting i cant use replace as it code replace any instance of cm the prefixes are held in the supplire table cross refer with the products table
prefixes are not always two chrachters for example can be TOW
SELECT * , left(prod.productcode, LEN(sup.prefix)) AS MyTrimmedColumn
FROM MSLStore1_Products prod ,supplier sup
WHERE prod.suppid = 9039 AND prod.SgpID = 171
and sup.supno = prod.suppid
Product Codes:
ProductCode
CMDI25L
CMDI300M
CMDI750M
CMXFFP5L
Prefixes:
Prefix
CM
CM
CM
CM
You could use SUBSTRING() for that:
SUBSTRING(prod.productcode, LEN(sup.prefix))
(concrete syntax may vary for different database-managers)
You might want to put your prefixes in another table, and run the productCode field through a filtering UDF to retrieve the final code.
Something like
SELECT * , dbo.FilterPCode(prod.productcode) AS MyTrimmedColumn
FROM MSLStore1_Products prod ,supplier sup
WHERE prod.suppid = 9039 AND prod.SgpID = 171
and sup.supno = prod.suppid
then just define a UDF that takes a string product code and removes any prefix from the front.
You might see a performance hit using a UDF like this for really massive queries, and if that's the case, it might be better to generate a table of table of product codes without the prefix linked to the product codes with the prefix. Don't know enough about the data schema to know if that's truly possible without getting cross links though.
how do i thought use this query and imortant the results from that into the products table external code field
SELECT * , right(prod.productcode, len(prod.productcode) - LEN(sup.prefix) ) AS ExternalCoode
FROM MSLStore1_Products prod ,supplier sup
WHERE prod.suppid = 9217 AND prod.SgpID = 123 and sup.supno = prod.suppid