ABAP OPEN SQL in re-engeneering an old program - abap

I am re-engeneering an old program to an S4/HANA system and I have stack in the below code:
LOOP AT ITAB.
CLEAR lv_stufe.
SELECT SINGLE stufe FROM prps INTO lv_stufe
WHERE pspnr = itab-projk .
IF lv_stufe <> '1'.
CLEAR : lv_up.
SELECT SINGLE up FROM prhi INTO lv_up
WHERE posnr = itab-projk .
CLEAR : lv_up1.
SELECT SINGLE up FROM prhi INTO lv_up1
WHERE posnr = lv_up.
CLEAR itab-prart.
SELECT SINGLE prart FROM prps INTO itab-prart
WHERE pspnr = lv_up1.
ENDIF.
ENDLOOP
Can we do it in 1 select?
Thanks
Elias
PS. Thanks Sandra. I think the below solves the problem. Of couse I already have change the ITAB to a more proper and I will create a GT table. Is it OK the below? My only concern is if I need LEFT or INNER. I think I need INNER.
select from prps inner join prhi
on prps~posnr = prhi~posnr
left join prhi as prhi2
on prhi~up = prhi2~posnr
fields prps~prart
where prps~stufe <> 1 and
prps~posnr = #itab-projk
into #itab-prart.

Related

How to write an Open SQL statement with substring in the JOIN ON condition? [duplicate]

I have the following select statement in ABAP:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
INTO corresponding fields of table GT_INSTMUNIC_F
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN EVER AS EV on
MUNIC~POD = EV~VREFER(9).
"where EV~BSTATUS = '14' or EV~BSTATUS = '32'.
My problem with the above statement is that does not recognize the substring/offset operation on the 'ON' clause. If i remove the '(9) then
it recognizes the field, otherwise it gives error:
Field ev~refer is unknown. It is neither in one of the specified tables
nor defined by a "DATA" statement. I have also tried doing something similar in the 'Where' clause, receiving a similar error:
LOOP AT gt_instmunic.
clear wa_gt_instmunic_f.
wa_gt_instmunic_f-mandt = gt_instmunic-mandt.
wa_gt_instmunic_f-bis = gt_instmunic-bis.
wa_gt_instmunic_f-ab = gt_instmunic-ab.
wa_gt_instmunic_f-zzelecdate = gt_instmunic-zzelecdate.
wa_gt_instmunic_f-ZZCERTDATE = gt_instmunic-ZZCERTDATE.
wa_gt_instmunic_f-CONSYEAR = gt_instmunic-CONSYEAR.
wa_gt_instmunic_f-ZDIMO = gt_instmunic-ZDIMO.
wa_gt_instmunic_f-ZZONE_M = gt_instmunic-ZZONE_M.
wa_gt_instmunic_f-ZZONE_T = gt_instmunic-ZZONE_T.
wa_gt_instmunic_f-USAGE_M = gt_instmunic-USAGE_M.
wa_gt_instmunic_f-USAGE_T = gt_instmunic-USAGE_T.
temp_pod = gt_instmunic-pod.
SELECT vrefer
FROM ever
INTO wa_gt_instmunic_f-vrefer
WHERE ( vrefer(9) LIKE temp_pod ). " PROBLEM WITH SUBSTRING
"AND ( BSTATUS = '14' OR BSTATUS = '32' ).
ENDSELECT.
WRITE: / sy-dbcnt.
WRITE: / 'wa is: ', wa_gt_instmunic_f.
WRITE: / 'wa-ever is: ', wa_gt_instmunic_f-vrefer.
APPEND wa_gt_instmunic_f TO gt_instmunic_f.
WRITE: / wa_gt_instmunic_f-vrefer.
ENDLOOP.
itab_size = lines( gt_instmunic_f ).
WRITE: / 'Internal table populated with', itab_size, ' lines'.
The basic task i want to implement is to modify a specific field on one table,
pulling values from another. They have a common field ( pod = vrefer(9) ). Thanks in advance for your time.
If you are on a late enough NetWeaver version, it works on 7.51, you can use the OpenSQL function LEFT or SUBSTRING. Your query would look something like:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN ever AS ev
ON MUNIC~POD EQ LEFT( EV~VREFER, 9 )
INTO corresponding fields of table GT_INSTMUNIC_F.
Note that the INTO clause needs to move to the end of the command as well.
field(9) is a subset operation that is processed by the ABAP environment and can not be translated into a database-level SQL statement (at least not at the moment, but I'd be surprised if it ever will be). Your best bet is either to select the datasets separately and merge them manually (if both are approximately equally large) or pre-select one and use a FAE/IN clause.
They have a common field ( pod = vrefer(9) )
This is a wrong assumption, because they both are not fields, but a field an other thing.
If you really need to do that task through SQL, I'll suggest you to check native SQL sentences like SUBSTRING and check if you can manage to use them within an EXEC_SQL or (better) the CL_SQL* classes.

Set a Variable in a case expression

I am looking to pass declared variables to build my string. I think I want to set my variable via a case expression but I have not done this before. Here is what I have done thus far.
DECLARE #stu_conv AS VARCHAR(5)
-- I think I need a select here.
set #stu_conv = CASE WHEN ITMMASTER.STU_0 ='KG' THEN'2.2'END
SELECT
YPRIMAT.YCROPYR_0
,ITMMASTER.TCLCOD_0
,SPRICLIST.DCGVAL_3
,ITMMASTER.TSICOD_2
,ITMMASTER.ACCCOD_0
,(BASPRI_0*#stu_conv) AS ImportstringAS Importstring
FROM LIVE.YPRIMAT
INNER JOIN LIVE.ITMMASTER ON YPRIMAT.ITMREF_0 = ITMMASTER.ITMREF_0
LEFT OUTER JOIN LIVE.SPRICLIST ON ITMMASTER.TCLCOD_0 = SPRICLIST.PLICRI1_0
WHERE SPRICLIST.PLICRD_0 = 'SPL000020'
I don't see the point for using a variable here, and trying to set it outside the query does not make sense, since you most likely want the value to reset for each row.
I would suggest moving the case expression into the query, as follows:
select
y.ycropyr_0,
i.tclcod_0,
s.dcgval_3,
i.tsicod_2,
i.acccod_0,
baspri_0 * case when i.stu_0 = 'KG' then 2.2 else 1 end as importstringas importstring
from live.yprimat y
inner join live.itmmaster i on y.itmref_0 = i.itmref_0
left outer join live.spriclist s on i.tclcod_0 = s.plicri1_0
where s.plicrd_0 = 'SPL000020'
I assumed that you want a value of 1 when stu_0 is not 'KG', but you can change this as needed.
Side note:
I modified your query to use table aliases. This makes the query shorter to write and somehow easier to read
you would need to prefix column baspri_0 with the table it belongs to (as your query is, it is not possible to tell)
I'm not sure why you're declaring a string and then multiplying it, but I would just inline the case (and add a default case?):
,(BASPRI_0 * CASE
WHEN ITMMASTER.STU_0 ='KG'
THEN 2.2
ELSE ???
END) AS Importstring

An object or column name is missing or empty. But its not?

I am on the 7th set of queries I have been working on and all of them have used SELECT * INTO some_table without an issue. For some reason tho the below query in SQL Server is throwing the error
An object or column name is missing or empty. For SELECT INTO
statements, verify each column has a name. For other statements, look
for empty alias names. Aliases defined as "" or [] are not allowed.
Change the alias to a valid name.
Any Idea on what it could be?
Note that running the query without the select into will result in data being returned and displayed as expected.
Select * into MYDB.MY_TBL
SELECT OT.U_ID AS "U_ID"
,R.E AS "E"
,R.IR AS "CKT"
,A.RI AS "OC"
,A.EQ AS "SEQ"
,A.HA AS "CHA"
,A.A_HA AS "ATE"
,A.BIL AS "BIL"
,A.CHA AS "CHAA"
,A.RAT AS "AMT"
,A.PRM AS "PREM"
,A.T_CHG AS "RAT"
,A.PER AS "LAS"
,A.S_BIL AS "BIL_A"
,A.CD AS "CDE"
,A.CBIL_J AS "BIL_J"
,A.AMT_D AS "TB"
,A.CRY AS "CTRY"
,A.RVW AS "RVW"
FROM MYDB.OTHER_TBL OT
JOIN [LINKEDSERVER\INST,0000].FE.dbo.tblR R
ON OT.E = R.E
JOIN [LINKEDSERVER\INST,0000].FE.dbo.tblA A
ON R.IR = A.IR
WHERE OT.U_ID = 'TEST'
You have two selects. I think you just want:
SELECT OT.U_ID AS "U_ID",
. . .
INTO MYDB.MY_TBL
FROM . . .
The INTO should follow the SELECT column list.
Or alternatively, you could use a subquery, but that does not seem necessary.
Where #GordonLinoff example works I realized what I forgot and it was my FROM () sub-query setup I normally use.
I will provide an example in contrast to Gordon's method.
IE:
Select * into MYDB.MY_TBL
FROM(
SELECT OT.U_ID AS "U_ID"
...
FROM MYDB.OTHER_TBL OT
WHERE OT.U_ID = 'TEST'
) SUB
Please note these two points:
1.You have two columns with given "CHA" alias
2.It Seems you need to rewrite the query as:
SELECT OT.U_ID AS "U_ID"
,R.E AS "E"
,R.IR AS "CKT"
,A.RI AS "OC"
,A.EQ AS "SEQ"
,A.HA AS "CHA_DUPLICATE"
,A.A_HA AS "ATE"
,A.BIL AS "BIL"
,A.CHA AS "CHA_DUPLICATE2"
,A.RAT AS "AMT"
,A.PRM AS "PREM"
,A.T_CHG AS "RAT"
,A.PER AS "LAS"
,A.S_BIL AS "BIL_A"
,A.CD AS "CDE"
,A.CBIL_J AS "BIL_J"
,A.AMT_D AS "TB"
,A.CRY AS "CTRY"
,A.RVW AS "RVW"
INTO MYDB.MY_TBL -- <<<<<<< NOTE
FROM MYDB.OTHER_TBL OT
JOIN [LINKEDSERVER\INST,0000].FE.dbo.tblR R
ON OT.E = R.E
JOIN [LINKEDSERVER\INST,0000].FE.dbo.tblA A
ON R.IR = A.IR
WHERE OT.U_ID = 'TEST'

The elements in the "SELECT LIST" list must be separated using commas

I want to do the following select, but it returned an error that I don't know what to do.
The elements in the "SELECT LIST" list must be separated using commas.
My version is NW 7.4. Could anyone help me ?
TYPES : BEGIN OF ty_meal,
carrid TYPE smeal-carrid,
mealnumber TYPE smeal-mealnumber,
text TYPE smealt-text,
END OF ty_meal,
ty_meal_s TYPE STANDARD TABLE OF ty_meal WITH EMPTY KEY.
DATA meals TYPE ty_meal_s.
SELECT smeal~carrid smeal~mealnumber smealt~text
INTO TABLE meals
FROM smeal
LEFT JOIN smealt
ON smealt~carrid = smeal~carrid
AND smealt~mealnumber = smeal~mealnumber
WHERE smealt~sprache EQ 'E'.
You need to separate the columns you SELECT with commas, like this
SELECT smeal~carrid, smeal~mealnumber, smealt~text
INTO TABLE #meals
FROM smeal
LEFT JOIN smealt
ON smealt~carrid = smeal~carrid
AND smealt~mealnumber = smeal~mealnumber
WHERE smealt~sprache EQ 'E'.
Before release 7.40 SP05, you cannot use the WHERE clause to filter on a column of a "right" table in a LEFT OUTER JOIN (ABAP 7.31 doc: "In outer joins, all comparisons that contain columns from the database table or view dbtab_right on the right side [...] These columns are not allowed as operands in the WHERE condition of the same SELECT statement.")
This restriction was logical because if one line is only in the left table, all the columns of the right table are considered "null", so, if there's a selection on a column of the right table, the line will not be selected (except if IS NULL is used).
The right way is to define the condition in the ON:
SELECT smeal~carrid smeal~mealnumber smealt~text
INTO TABLE meals
FROM smeal
LEFT JOIN smealt
ON smealt~carrid = smeal~carrid
AND smealt~mealnumber = smeal~mealnumber
AND smealt~sprache EQ 'E'. " <==== move it from WHERE to ON
I've solved my problem. It's the mandt, I was trying to do the select with the mandt
`ON ( aufk~mandt EQ afih~mandt AND aufk~aufnr EQ afih~aufnr )`
but itns't necessary. I've changed to
`ON (aufk~aufnr EQ afih~aufnr )`

Select all columns from one table and one from another where column equals variable

Sorry for the long title.
I have a statement which needs to grab all the columns from one row from BinConfig:
SELECT *
FROM BinConfig WITH(NOLOCK)
WHERE IssuerKey = #IssuerKey
But I also need to grab a single column from one row from CardRangeGroup also based on that IssuerKey column.
What I've tried:
SELECT
BinConfig.*, CardRangeGroup.Name
FROM
BinConfig
JOIN
CardRangeGroup WITH(NOLOCK)
WHERE
#IssuerKey = BinConfig.IssuerKey
AND #IssuerKey = CardRangeGroup.IssuerKey
Which gives me a syntax error near WHERE. I've tried to find resources online, but everywhere I look I can't find anything explaining how to select rows based on a passed in variable. Any help?
You need to specify how the tables should be joined. Try this:
SELECT BinConfig.*, CardRangeGroup.Name
FROM BinConfig
JOIN CardRangeGroup ON BinConfig.IssuerKey = CardRangeGroup.IssuerKey
WHERE #IssuerKey = CardRangeGroup.IssuerKey
The with(nolock) might not be needed (or a good idea) so I removed it.
try this , you don't need to use where
SELECT BinConfig.*, CardRangeGroup.Name FROM BinConfig JOIN
CardRangeGroup
ON CardRangeGroup.IssuerKey = BinConfig.IssuerKey AND #IssuerKey = CardRangeGroup.IssuerKey