Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Loop Range table to Build SQL Statement

Former Member
0 Likes
4,430

I would like to loop Through a RANGES type table to build a SQL Statement something like this.

Data: SQLSTR type C.

Loop at LS_Select into WA_LS_select.

SQLSTR = SQLSTR + WA_LS_select-Fieldname in WA_LS_select.

endloop

Select * from TABLEX where ( SQLSTR )

Is this possible if so could someone please give me a little sample code. Additionally it is possible that in my ranges table I could have multiple items for the same field name..

1 ACCEPTED SOLUTION
Read only

suresh_datti
Active Contributor
0 Likes
2,769

Hi Hubert,

try changing the loop as follows..


assuming ls_select is your RANGES
Loop at LS_Select.
concatenate SQLSTR LS_select-low
 into SQLSTR.
endloop

Regards,

Suresh Datti

19 REPLIES 19
Read only

suresh_datti
Active Contributor
0 Likes
2,770

Hi Hubert,

try changing the loop as follows..


assuming ls_select is your RANGES
Loop at LS_Select.
concatenate SQLSTR LS_select-low
 into SQLSTR.
endloop

Regards,

Suresh Datti

Read only

0 Likes
2,769

I did not understand your requirement but here is one suggestion - my assumption is you do not want to use select option directly in code.

Suppose I have S_MATNR as select optopn.

First get all the Materials for this S_MATNR from MARA table into another internal table.

Then you can loop at this table and select your code

LOOP AT I_MARA.

SELECT DATA FROM TABLE WHERE MATNR = I_MARA-MATNR.

ENDLOOP.

Else you can also use FOR ALL ENTRIES option.

Read only

former_member186741
Active Contributor
0 Likes
2,769

aSSUMING THE TABLE AND FIELDNAME IS CONSTANT:

DATA l_sql TYPE string.

loop at r_range.

if sy-tabix = 1.

concatenate 'table-fieldname = ' r_range-low

into l_sql separated by space.

else.

concatenate l_sql 'or table-fieldname = ' r_range-low

into l_sql separated by space.

endif.

endloop.

Select * from TABLEX where (l_sql).

.........

If you want to use the HIGH and LOW of the range you could modify it slightly to use

concatenate 'table-fieldname between ' r_range-low

'and' r_range-high into l_sql separated by space.

Read only

Former Member
0 Likes
2,769

This would be pretty difficult. You will have to handle things like NE, CP, EXCLUDE. Why not just use the range table?

Rob

Read only

0 Likes
2,769

Rob,

This is exactly what I would like to do is use the Range table. My table contains data like this.

fieldname-sign-option-low-high

zip-I-eq---30152

zip-I-bt-30111-30113

yeare-lt---2005

etc etc....

What I want to do is loop through this table to build a sql statement.

Is this possible?

Read only

0 Likes
2,769

Hi,

U can write a select like this.

select <your fields> from <table> into table <IT>

where

zip_field in zip (This is the range in your table)

and year in year(year in your range table)

Regards,

GSR.

Read only

0 Likes
2,769

Pls.look into the below code..may it useful for u

loop <rangestable> into <wa_range>

select <f1> <f2> from <db> into table <itab>

where <field> in <wa_range>.

clear <wa_range>.

endloop.

Read only

0 Likes
2,769

Hi Hubert

yes you can loop through this table then build the select statement.

loop at itab_range.

use conditional statements then hard code the required select statement for ex.

if itab_range-fieldname eq 'zip' and itab_range-option eq 'eq'.

select * from zemp where zip bt itab_range-low and itab_range-high.

endif.

regards

kishore

Read only

0 Likes
2,769

Eswar,

You seem to be the closest to what I want, but would that not create multiple select statements for each field?

Read only

0 Likes
2,769

hope in this case it will create multiple statements bcoz we will get only one row at a time to check in select statement.

or else u can create separate range for each field to check in a single select statement (Performance)

Read only

0 Likes
2,769

I was considering making a range table for each possible entry, but this could endup being a little over 80.

Then I would have to also include every on in the select statement. I was really hoping to avoid this since, most of the time I expect the user to only select 10 to 20 variables.

Is it possible to convert a range table into a string, maybe a function module or something? what does it do at run time?

Read only

0 Likes
2,769

Well, I was suggesting that you just use all of the range tables as is. I'm sure you can build the logic to do what you want, but it will be difficult and time consuming. In the end it probably will be just as long and no more efficient.

rob

Read only

former_member186741
Active Contributor
0 Likes
2,769

I have coded this and it works, but I have to wonder why you would ever want to do it this way given that the sql can just refer directly to the ranges (or select-options in this example).

I had a program which had a few select options within it's sql, I changed it to dynamically generate references to the select options instead of hard-coding the 'in' clauses in the sql:

DATA l_sql TYPE string.

SELECT-OPTIONS S_bLART for bSID-bLART.

SELECT-OPTIONS s_BRAN1 for KNA1-BRAN1.

SELECT-OPTIONS s_REGIO for KNA1-REGIO.

define append_sql.

if l_sql is initial.

concatenate &1 'in' &2 into l_sql separated by space.

else.

concatenate L_SQL 'AND' &1 'IN' &2 into l_sql separated by space.

ENDIF.

END-OF-DEFINITION.

APPEND_SQL 'BSID~BLART' 'S_BLART'.

APPEND_SQL 'KNA1~BRAN1' 'S_BRAN1'.

APPEND_SQL 'KNA1~REGIO' 'S_REGIO'.

SELECT bsidbukrs bsidkunnr bsid~belnr

kna1regio kna1bran1 kna1~name1

FROM bsid

JOIN vbrk ON vbrkvbeln = bsidvbeln

JOIN knvv ON knvvkunnr = vbrkkunag

AND knvvvkorg = vbrkvkorg

AND knvvvtweg = vbrkvtweg

AND knvvspart = vbrkspart

JOIN kna1 ON kna1kunnr = knvvkunnr

INTO CORRESPONDING FIELDS OF TABLE T_BSID

WHERE bsid~bukrs = p_bukrs

AND bsid~kunnr IN s_kunnr

AND bsid~budat <= w_key_date

  • AND bsid~blart IN s_blart "now in l_sql

  • AND kna1~bran1 IN s_bran1 "

  • AND kna1~regio IN s_regio "

AND (l_sql)

.

Read only

Former Member
0 Likes
2,769

Hi Hubert,

You must build your SQL statement dynamically like this...

<b>DATA sqlstr(100).</b>

LOOP AT ls_select INTO wa_ls_select.
 IF sqlstr IS INITIAL.
   IF wa_ls_select-option EQ 'eq' AND wa_ls_select-sign EQ 'I'.
     CONCATENATE wa_ls_select-fieldname 'EQ' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
  IF wa_ls_select-option EQ 'eq' AND wa_ls_select-sign EQ 'e'.
     CONCATENATE wa_ls_select-fieldname 'NE' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
  IF wa_ls_select-option EQ 'bt' AND wa_ls_select-sign EQ 'I'.
     CONCATENATE wa_ls_select-fieldname 'BETWEEN' wa_ls_select-low
    'AND' wa_ls_select-high
     INTO sqlstr
     SEPARATED BY space.
   ENDIF.
   IF wa_ls_select-option EQ 'lt' AND wa_ls_select-sign EQ 'I'.
     CONCATENATE wa_ls_select-fieldname 'LE' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
   IF wa_ls_select-option EQ 'lt' AND wa_ls_select-sign EQ 'e'.
     CONCATENATE wa_ls_select-fieldname 'LT' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
   IF wa_ls_select-option EQ 'gt' AND wa_ls_select-sign EQ 'I'.
     CONCATENATE wa_ls_select-fieldname 'GE' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
   IF wa_ls_select-option EQ 'gt' AND wa_ls_select-sign EQ 'e'.
     CONCATENATE wa_ls_select-fieldname 'GT' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
ELSE.
   CONCATENATE sqlstr 'AND' INTO sqlstr SEPARATED BY space.
   IF wa_ls_select-option EQ 'eq' AND wa_ls_select-sign EQ 'I'.
     CONCATENATE wa_ls_select-fieldname 'EQ' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
  IF wa_ls_select-option EQ 'eq' AND wa_ls_select-sign EQ 'e'.
     CONCATENATE wa_ls_select-fieldname 'NE' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
  IF wa_ls_select-option EQ 'bt' AND wa_ls_select-sign EQ 'I'.
     CONCATENATE wa_ls_select-fieldname 'BETWEEN' wa_ls_select-low
    'AND' wa_ls_select-high
     INTO sqlstr
     SEPARATED BY space.
   ENDIF.
   IF wa_ls_select-option EQ 'lt' AND wa_ls_select-sign EQ 'I'.
     CONCATENATE wa_ls_select-fieldname 'LE' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
   IF wa_ls_select-option EQ 'lt' AND wa_ls_select-sign EQ 'e'.
     CONCATENATE wa_ls_select-fieldname 'LT' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
   IF wa_ls_select-option EQ 'gt' AND wa_ls_select-sign EQ 'I'.
     CONCATENATE wa_ls_select-fieldname 'GE' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
   IF wa_ls_select-option EQ 'gt' AND wa_ls_select-sign EQ 'e'.
     CONCATENATE wa_ls_select-fieldname 'GT' wa_ls_select-low
        INTO sqlstr
        SEPARATED BY space.
   ENDIF.
 ENDIF.
ENDLOOP.


Select * from TABLEX where ( SQLSTR ).

Read only

0 Likes
2,769

Hi Wenceslaus, what do you mean by "MUST" build the sql like this?

Read only

0 Likes
2,769

Hi Neil,

Since the requirement was to build sql from a table where he had not used RANGES:

fieldname-sign-option-low-high

zip-I-eq---30152

zip-I-bt-30111-30113

yeare-lt---2005

Then I think the possible way for this is that he could parse the contents of the table and build SQL query. Still there could be alternative ways of doing this...

Regards,

Wenceslaus.

Read only

0 Likes
2,769

maybe I've misunderstood, but Hubert specifically said he wants to use a RANGES type table.

Read only

Former Member
0 Likes
2,769

Hi,

Here is the code if it for ranges table.

REPORT  ZEN_COV.

TABLES: mara.

SELECT-OPTIONS: ls_sel FOR mara-matnr.

DATA: t TYPE i.

DATA datstr(2000).
DATA tmpstr(2000).

LOOP AT ls_sel.
  IF datstr IS NOT INITIAL.
    CONCATENATE datstr 'AND' INTO datstr SEPARATED BY space.
    tmpstr = datstr.
  ENDIF.

  IF ls_sel-option EQ 'EQ' AND ls_sel-sign EQ 'I'.
    CONCATENATE tmpstr 'mara~matnr' 'EQ' ls_sel-low
    INTO datstr SEPARATED BY space.
  ENDIF.
  IF ls_sel-option EQ 'BT' AND ls_sel-sign EQ 'I'.
    CONCATENATE tmpstr 'mara~matnr' 'BETWEEN' ls_sel-low
    'AND' ls_sel-high INTO datstr SEPARATED BY space.
  ENDIF.
  IF ls_sel-option EQ 'EQ' AND ls_sel-sign EQ 'E'.
    CONCATENATE tmpstr 'mara~matnr' 'NE' ls_sel-low
    INTO datstr SEPARATED BY space.
  ENDIF.
  IF ls_sel-option EQ 'LT' AND ls_sel-sign EQ 'I'.
    CONCATENATE 'mara~matnr' 'LE' ls_sel-low
    INTO datstr SEPARATED BY space.
  ENDIF.
  IF ls_sel-option EQ 'LT' AND ls_sel-sign EQ 'E'.
    CONCATENATE tmpstr 'mara~matnr' 'LT' ls_sel-low
    INTO datstr SEPARATED BY space.
  ENDIF.
  IF ls_sel-option EQ 'GT' AND ls_sel-sign EQ 'I'.
    CONCATENATE tmpstr 'mara~matnr' 'GE' ls_sel-low
    INTO datstr SEPARATED BY space.
  ENDIF.
  IF ls_sel-option EQ 'GT' AND ls_sel-sign EQ 'E'.
    CONCATENATE tmpstr 'mara~matnr' 'GT' ls_sel-low
    INTO datstr SEPARATED BY space.
  ENDIF.

ENDLOOP.

SELECT * FROM mara WHERE (datstr).
ENDSELECT.

regards

austin

Read only

Former Member
0 Likes
2,769

Ok. I finaly solved it myself.

All the ideas above were great but, I was really looking for something that was a litte more standard SAP, rather than custom built from scratch.

SAP has a function module that you can pass a range table too, and it basically gves you back the where statement really cool.

-- Take a look at FREE_SELECTIONS_RANGE_2_WHERE

Thanks again for all your help...