a complete guide to opensql statements

Upload: ricky-das

Post on 03-Jun-2018

230 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/12/2019 A Complete Guide to OpenSQL Statements

    1/30

    A complete guide to OpenSQL statements - Step-by-step tutorial

    with screenshotsPosted byTamas HolicsinABAP Developmenton May 21, 2014 10:00:54 AM

    inShare40

    In my first blog post on SCN, Idlike to give an overview of the OpenSQL query syntax.Starting from the simplest SELECT statement Idlike to demonstrate all language elementsof OpenSQL, gradually building up a very complex database query. For each step, Illprovide a business example and a screenshot so you can see the result of each SELECTquery. I have used the Flight demo database available in every SAP system, so you cantest the queries for yourself.

    Note: in this post I will not discuss performance-related topics in detail. That would make

    this post way too long. Maybe in a future post

    So letsbegin!

    Example 1: the simplest SELECT statement

    There are three mandatory parts of a SELECT statement, basically defining what you wantto read from which table and where to put the result:

    1, After the SELECT keyword, we must specify the fields of the so called resultset(resultingsetin the SAP help). Here we define which fields we want to see in the result of

    the selection. In Example 1, we entered *,a special character that means that all fieldsfrom the defined table(s) will be returned. This is a handy feature but keep in mind if thatyou select all fields from a table that consists of 250 columns, and you use only five of them,that wastes a lot of CPU, memory and network resources. In this case it is better to list thefive fields explicitly (especially if you select a lot of records).

    2, the FROM clause defines which table(s) to read the data from. Here you must specify atleast one table or view that exists in the Data Dictionary. In the first example we will onlyaccess one table, and the later examples will use more tables.

    3, The INTO clause defines where to put the results, which is usually called as a "workarea".Here you must define the data object that will hold the result set using one of theoptions below:

    - INTO x, where x is a structure.- INTO TABLE y, where y is an internal table.- APPENDING TABLE z, where z is an internal table. In this the result set is appended tothe internal table (not clearing the existing contents).

    http://scn.sap.com/community/abap/blog/2014/05/21/a-complete-guide-to-opensql-statements--step-by-step-tutorial-with-screenshotshttp://scn.sap.com/community/abap/blog/2014/05/21/a-complete-guide-to-opensql-statements--step-by-step-tutorial-with-screenshotshttp://scn.sap.com/community/abap/blog/2014/05/21/a-complete-guide-to-opensql-statements--step-by-step-tutorial-with-screenshotshttp://scn.sap.com/people/tamas.holics3http://scn.sap.com/people/tamas.holics3http://scn.sap.com/people/tamas.holics3http://scn.sap.com/community/abap/bloghttp://scn.sap.com/community/abap/bloghttp://scn.sap.com/community/abap/bloghttp://scn.sap.com/community/abap/bloghttp://scn.sap.com/people/tamas.holics3http://scn.sap.com/community/abap/blog/2014/05/21/a-complete-guide-to-opensql-statements--step-by-step-tutorial-with-screenshotshttp://scn.sap.com/community/abap/blog/2014/05/21/a-complete-guide-to-opensql-statements--step-by-step-tutorial-with-screenshots
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    2/30

    - INTO (a,b,c, ... ), where a, b, c etc. are variables with elementary types

    There are several instructions in the SAP help regarding the prerequisites of work areas(data type etc.) and assignment rules (automatic conversions etc.) which I don't want to

    copy and paste here. I'd anyway recommend either using a structure identical to the fieldselection, or using the "CORRESPONDING FIELDS OF" addition. This will assign theselected fields to the fields of the work area based on the field name (not from left to right).

    For all constructs except INTO TABLE, if the result set is empty, the target remainsunchanged.

    Hint: the INTO clause can be omitted in a special case, when you use a group function tocount the number of lines that match the WHERE clause. In this case system variable SY-DBCNT will hold the number of records found. See Example 5.

    Note: The INTO clause is missing from the screenshots because the tool Iveusedautomatically generates it. Anyway, all the examples would use the INTO TABLE variant tofetch all matching records at once.

    Business requirement: we want to select all data for 100 bookings from the booking table.

    Really simple, right?

    How to achieve this? Simply define "*" after the SELECT keyword, specify table SBOOK inthe FROM clause and limit the number of records fetched using the UPTO N ROWS

    clause. This can be used to define the maximum number of lines we want the query toreturn. This is typically used for existence checks (UP TO 1 ROWS), but in this example wehave limited the query to return maximum 100 records. Unless you specify the ORDER BYclause, this will return 100 arbitrary records, so you cannot know which 100 it will return.

  • 8/12/2019 A Complete Guide to OpenSQL Statements

    3/30

    Screenshot 1: Simply select 100 bookings from table SBOOK

    Example 2: Adding a WHERE clause and a table join

    The WHERE clause

    Usually SELECT statements do not read all the contents of a table (typical exceptions aresmall customizing tables holding a few records), but return only specific entries. TheWHERE clause is used to filter the result set, or in other words tell the database whichrecords to retrieve. Here you define a logical expression that the database will evaluate foreach row in the database.

    Business requirement: return only bookings of Lufthansa (field CARRID must contain LH)and cancelled bookings are not needed (CANCELLED must be equal to space).

    The database will evaluate this condition for each record in the table and if the condition istrue, it will be placed into the result set. You can write much more complex logicalconditions as we will see in the following examples. Any number of logical expressions canbe linked to a logical expression using keywords AND or OR and the result of a logicalexpression can be negated using keyword NOT. Keep the order of evaluation in mind(ensure the proper use of parentheses). Simple operators used to compare field values areEQ, NE, GT, LT, GE and LE (equivalent to =, , >, =,

  • 8/12/2019 A Complete Guide to OpenSQL Statements

    4/30

    Table joins

    The second interesting addition in this example is the table join. Often data required for a

    specific business process is stored in several tables. Although it could be an option to selectdata from each table using separate SELECT commands and combine the results usingABAP code executed on the application server, many times it is more convenient andperformant to use only one SELECT statement to read all the tables at once.

    Business requirement: read customer data from table SCUSTOM for the customer of eachbooking.

    This is achieved using a so called tablejoin:a construct that instructs the database toaccess a further table based on a condition. This so called joincondition(or joinexpression)represents the logical link between the two tables. In this example it is the

    customer number: for each booking in table SBOOK the database will search for thecustomer data in table SCUSTOM based on the customer number.

    Because we use *to define the fields of the result set and we read from two tables in thisexample, the result set contains all the fields from both tables. If there is a field with thesame name in both tables, only one will be returned (the one from the last table in theFROM clause - each join overwrites the field contents).

    Note: the tool Iveused for the screenshots automatically generates a separate field in thiscase. This is the reason why you can see duplicate fields.

    The syntax of a join condition is almost the same like in a WHERE clause with somenotable differences which I dontwant to copy and paste here from the SAP Help (can notuse subqueries, must use AND to link logical expressions etc).

    There are two kinds of table joins in OpenSQL: inner joins and outer joins. We will discussthe difference in the next example.

    Hint: SELECT statements using table joins bypass SAP buffering.

  • 8/12/2019 A Complete Guide to OpenSQL Statements

    5/30

    Screenshot 2: adding a WHERE clause and a table join

    Example 3: Adding data from another two tables

    Fortunately OpenSQL allows to join multiple tables together at once: maximum 25 tablescan be joined in a SELECT statement. Here in this example we add data from two moretables: T005T which holds country data and GEOT005S which contains geographicinformation of regions.

    Business requirement: Display the country name instead of country code and display thelatitude and longitude of the region of the customer.

    One special thing in this example is the join condition of table T005T. This table is languagedependant, so a language key is needed to get the textual description of a country in aspecific language. Remember: the join condition tells the database how to get a recordfrom table B based on a record from table A (A being the left hand side and B being theright hand side table). This is special now because we use the logon language of thecurrent user from field SY-LANGU. All fields of the SY structure can be used in joinconditions (current date, time, system ID etc.) as well as WHERE and HAVING clauses.

    What would happen if we would omit the language key specification? The database wouldreturn multiple rows with the same booking, customer and region information. Why? Simplybecause there are more than one entries in table T005T for the same country. Letssay wehave two entries for country DE:it is Deutschlandin German and it is GermanyinEnglish. In case of a German customer, the database engine would evaluate the joincondition (T005T-LAND1 = SCUSTOM-COUNTRY) for both records, and both would betrue, so two rows would be returned: one with English text and one with German text.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456735/2_inner_join_and_where_clause.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    6/30

    Screenshot 3: multiple table joins. Notice that all lines contain a latitude and a longitude.

    Example 4: Another kind of table join - Left outer join

    Here comes the difference between the two kinds of table joins in OpenSQL: the inner joinand the outer join (for ex. SELECT* FROM A INNER JOIN B/ SELECT* FROM A LEFTOUTER JOIN B).

    Basically the difference is the behavior in case there is no corresponding entry in table B fora record in table A. In case of an inner join, there would be no record placed into the resultset. In case of a left outer join, there would be a record in the result set, but all fields comingfrom table B would be empty.

    This is behavior is very easy to see in this example: we added geographic coordinates toour query in the previous example using an inner join. Table GEOT005S containscoordinates for country regions. Whenever a record was not found in table GEOT005S forthe region of a customer, the whole line was dropped from the result set. This is why you

    can only see customers with non-empty latitude and longitude.

    In the current example we add the latitude and longitude of the region of the customer usinga left outer join. As you can see in the screenshot, there is only one customer, for whomthere are coordinates returned. For all other records, the DB did not find a suitable record inGEOT005S, so the coordinates are empty. If GEOT005S would be accessed using anINNER JOIN, these records would be excluded from the result set.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456736/3_another_inner_join_geocode.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    7/30

    Screenshot 4: table join using a left outer join. Notice that now customers with emptylatitude and longitude appear on the list.

    Note: if you have carefully checked the screenshot, you could notice that there is acustomer with a region defined (IL)but there are no coordinates displayed. The reasoncould be that there is no entry in GEOT005S for country USregion IL,but it is not thecase. Somehow the standard flight demo database contains incorrect entries having anunnecessary space. This is the reason why the DB does not find the matching record, sinceIL IL.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456744/5_error_reason.jpghttp://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456743/4_left_outer_join_error.jpghttp://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456744/5_error_reason.jpghttp://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456743/4_left_outer_join_error.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    8/30

  • 8/12/2019 A Complete Guide to OpenSQL Statements

    9/30

  • 8/12/2019 A Complete Guide to OpenSQL Statements

    10/30

    reduce the volume of data that has to be transferred from the database to the applicationserver. Of course on the other side, this needs more resources from the database.

    Hint: With the use of GROUP BY, the statement SELECT avoids the SAP buffering.

    Example 6: defining groups for the group functions

    Wevelearned that group functions perform certain calculations on groups of databaserecords. If we do not explicitly specify a group, then all the records in the result set areconsidered as one big group, as in the previous example.

    Business requirement: display the number of (non-cancelled Lufthansa) bookings percustomer.

    In this case we form groups of database records based on the customer number by listingfield ID in the group by clause. Also, we have to enter the ID field of table SCUSTOM in theSELECT clause before the group function.

    Screenshot 6: Grouping rows by customer ID. The COUNT group function is performed onevery group to count the number of bookings for each customer.

    As you can see, now the database engine returns as many records as many customer IDswe have in the result set, and the number of relevant bookings next to them. Exactly whatwe wanted.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456748/9_group_by_clause_1.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    11/30

    Note: in all of our previous examples, weveused the *sign in the SELECT clause (fieldlist). However, here we have to explicitly define the fields needed to create groups ofrecords. It is mandatory to add the table name and the ~ sign before the name of adatabase field, if more than one table has a field with the same name.

    Example 7: Adding extra information

    Business requirement: display additional fields in the result list (name, city, country, regioncode, coordinates).

    How to do it? Simply add them to the SELECT clause after the customer number before theCOUNT function. Keep in mind to add the field to the GROUP BY clause too, otherwise youwill encounter a syntax error. The fields you use to form groups must be in the SELECTclause, and nothing else should be in the SELECT clause that is not in the GROUP BYclause and is not a group function.

    Screenshot 6: additional fields are displayed in the list.

    Note:Now you could wonder that in the previous example I told you that by adding fields

    before the group function is how we define groups, but here the number of bookings did notchange. The reason is that we have added fields from tables that have a 1:1 relation to thecustomer. A customer has only one name, a city is in one country and region and has one

    pair of coordinates. If we would have chosen to add the Flight Class field (First class /Business / Economy), then the result set could contain more than one line per customer: asmany lines per customer as many kind of flights he/she had. We will see how this works inexample 15.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456750/12_group_by_clause_4.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    12/30

    Example 8: Defining the order of records in the result set

    You can use the ORDER BY clause in a query to define the sort order of the records

    returned. Simply list all the fields that you want to use as a sort criteria. You can usekeywords ASCENDING and DESCENDING for each field to specify the sort mode(ASCENDING is the default so it can be omitted).

    Business requirement:display the customers with the most bookings.

    What do we do now? We sort the list by the result of the COUNT function in descendingorder and then by the name of the customer.

    Screenshot 7: the result set is sorted using the ORDER BY clause.

    As you can see, there are several customers who have more than ten bookings (non-cancelled, Lufthansa).

    Note: If all key fields are in the field list and a single database table is specified after FROM(not a view or join expression), the addition PRIMARY KEY can be used to sort the resultset in ascending order based on the primary key of the table.

    Example 9: Filtering based on a group function

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456751/13_order_by_clause.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    13/30

    Business requirement: the boss is only interested in customers having more than ten non-cancelled Lufthansa bookings.

    How do we do this? I guess the first idea would be to add a new condition to the WHEREclause to filter records where the COUNT function is higher than ten. However, this will not

    work because of the OpenSQL (and SQL in general) language.

    The reason is that the WHERE clause filters the database records before the groups arecreated by the database engine. After the groups are created, the group functions arecalculated and the result set is created. The WHERE clause cannot be used to filter basedon the group function results.

    In cases like these, the HAVING clause must be used. This is similar to the WHERE clause,but the difference is that it is evaluated after the groups are created and group functions areperformed. To simply put: to filter based on the result of group functions, the HAVING

    clause must be used (also called as group condition).

    Screenshot 8: using the HAVING clause to filter the result set based on group functions.

    As you can see on the screenshot, now only 23 records returned, although we have allowedto have 100 records by using the UP TO N ROWS addition. So this means that there are 23customers having more than ten non-cancelled Lufthansa bookings.

    Note: If you dontspecify any groups using the GROUP BY clause, the HAVING clause willconsider the whole result set grouped into one line. For a quick example assume we have

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456755/14_having_clause.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    14/30

    10 records in table SCARR. The query SELECTCOUNT( * ) FROM scarr HAVING count( *) GT 0will return one single line with the number of records in the table, but the querySELECTCOUNT( * ) FROM scarr HAVING count( * ) GT 10will not return any lines(empty result set).

    Example 10: using subqueries

    The possibility to combine multiple SELECT statements into one is a very handy feature inOpenSQL. This is mostly used when you dontknow for exactly the filter criteria duringdesign time or when you have to use a comparison to a dynamically calculated value.

    Business requirement: the list must include only customers who have never cancelled aflight (any airline, not only Lufthansa). At the first glimpse, you could logically ask that this isalready done, since we have cancelledEQ spacein our WHERE clause. This is notcorrect, because this only influences our group function so that only non-cancelled bookings

    are counted. This means that if a customer has 20 bookings with one cancelled, he/she willbe on our list with 19 bookings. According to our requirement, we dontwant this customerto be on our list, so how do we achieve that?

    An easy way to solve this is to add a so called subquery to our WHERE clause whichchecks if there is a cancelled booking for the customer.

    Subqueries in general

    Basically a subquery is a SELECT statement in parentheses used in a logical expression.

    There is no need to have an INTO clause because the result of the subquery will beprocessed by the database engine.

    How are the results of subqueries evaluated? This depends on if the subquery is correlatedor not. If a subquery uses fields from the surrounding SELECT statement in its WHEREcondition, is called a correlated subquery. In this case, the result of the subquery will beevaluated for each line in the result set of the surrounding SELECT statement (in whichsWHERE clause the subquery is placed). This implies that the subquery is for each record inthe result set of the surrounding SELECT statement. On the other hand, a subquery withoutany reference to the surrounding SELECT statement is executed only once.

    There are different operators which one can use with subqueries, we will use the EXISTSoperator (negated) in this example. Illdiscuss the others in Example 13.

    Subqueries can be nested which means that you can put a subquery in the WHERE clauseof a subquery. We will see an example of this later in Example 13.

  • 8/12/2019 A Complete Guide to OpenSQL Statements

    15/30

    Now take the current example: we need to check if a customer has a cancelled booking, sowe have to create a relation between the customer ID in the result set of our outer SELECTstatement and the subquery (so we use a correlated subquery). This is done by adding acondition to the WHERE clause of the subquery to match the customer IDs.

    Screenshot 9: using a subquery. As you can see, now only 20 records are returned, sothree customers had a cancelled flight on our previous list.

    Table aliases

    Notice that here we must use so called tablealiasesbecause we select from the sametable in both the surrounding query and the subquery. This means that we must somehowexplicitly define the table name for the fields to be compared, otherwise the DB enginewould not know which table field do we refer to. This is done with the use of table aliases.Basically you can give a name to your tables and refer to them using the alias. Here Ivedefines sqas an alias for the subquery. You have to use the ~ character between thetable alias and the field name (and of course between the table name and field name as inthe previous examples).

    Notes: Subqueries cannot be used when accessing pool tables or cluster tables.

    the ORDER BY clause cannot be used in a subquery. If a subquery is used, the Open SQL statement bypasses SAP buffering.

    Note: subqueries can be used in the HAVING clause too as seen in example 14.

    Hint: we could have solved the requirement without a correlated subquery. In this case, thesubquery would select all the customers who had a cancelled booking, and the surrounding

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456756/15_subquery.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    16/30

    SELECT statement would check every customer if it is in the result set of the subquery:

    Simplified example:

    SELECT ...WHERE customid NOT IN ( select custom id from sbook where cancel led EQ 'X' ).is equal toSELECT ...WHERE not exists (se lect bookid from sbook as sq where sq~customid EQ sboo k~customidand cancel led EQ 'X' )

    Example 11: Special operators

    In all the previous examples we have only used the EQ(same as =)operator and the GT(>=) to compare field values. However, there are more complex ones too.

    BETWEEN

    This operator is very simple, it is basically =together.

    Business requirement:exclude only customers from our list, who have a cancelled bookingsin the first quarter of 2005.

    The syntax for this is fieldBETWEEN value1 AND value2.

    Hint: from the business perspective we expect more customers in the result set, since weexclude less customers due to a more restrictive subquery.

    Screenshot 10: using the BETWEEN operator. As you can see, there are 21 customers onour list, so there is one customer who appears again (had cancellation before or after Q1 of2005).

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456757/16_between_operator.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    17/30

    LIKE

    This expression is a very flexible tool for character string comparisons based on a pattern.The pattern can be defined using wildcard characters: "%" represents any character string(even an empty one) and "_" represents any single character. The LIKE expression is case

    sensitive, and blank characters at the end of the pattern are ignored (LIKE __is equal toLIKE __ ).

    Business requirement (quite strange): restrict our list further to only contain customerswith a name starting with A.

    We add nameLIKE A%to the WHERE clause to achieve this.

    Screenshot 11: using the LIKE operator to filter the list based on the name of the customer.

    Note: What to do if we want to search for records that contain _in a specific field? Sincethis is a reserved symbol, we have to use the addition ESCAPE, which allows an escapecharacter can be defined. This escape character cancels the special functions of wildcardcharacters (simply place the escape character before the wildcard character to becancelled).

    A quick example: select all material numbers which contain an underscore:

    Wrong approach (returns every material number):SELECT matnr FROM marawhere matnr LIKE '%_%'

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456758/17_like_operator.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    18/30

    Good approach:SELECT matnr FROM marawhere matnr LIKE '%~_%' ESCAPE '~'

    Hint: It is not possible to specify a table field as a pattern.

    Business requirement (even more strange): now we want to only see customers with a

    name starting with Aand having das the third letter.

    Screenshot 12: using the LIKE operator with both special characters %and _.As youcan see, we still have three customers who match all our selection criteria.

    IN

    This operator allows you to compare a field to a set of fixed values. This comes handy as itcan replace a longer and much less readable expression:

    fieldIN (01,03,05)is equal to the much longer fieldEQ 01or field EQ 02or field EQ03

    Business requirement: extend our selection to customers of American Airlines and UnitedAirlines too.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456759/18_like_operator_2.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    19/30

    Screenshot 13: using the IN operator to count bookings of other airlines too. As expected,we now have much more customers who match the less restrictive selection criteria.

    Note: the IN operator can be used with a selection table too, as seen in chapter 17.

    Example 12: Other group functions

    So far we have only used the COUNT group function to count the number of bookings thatmatch our selection criteria. There are a total of five group functions available in OpenSQL.

    The remaining four that we haventseen yet are all mathematical calculations: SUM, MIN,MAX and AVG that calculate the total, minimum, maximum and average of a fieldrespectively.

    There are some restrictions related to the use of group functions:

    If the addition FOR ALL ENTRIES is used in front of WHERE, or if cluster or pool tables are listedafter FROM, no other aggregate expressions apart from COUNT( * ) can be used.

    Columns of the type STRING or RAWSTRING cannot be used with aggregate functions. Null values are not included in the calculation for the aggregate functions. The result is a null value

    only if all the rows in the column in question contain the null value.

    Business requirement: the boss wants to see the total, average, minimum and maximum ofthe booking price for each customer (in the currency of the airline).

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456760/19_in_operator.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    20/30

    Screenshot 14: using all group functions (MIN, MAX, SUM, AVG, COUNT).

    Note: just like with the COUNT function, the DISTINCT keyword can be used to perform thegroup function only on distinct values (so the result of SUM( DISTINCT A ) for two recordshaving value 10 in a field A would be 10).

    Note: the data type for AVG and SUM must be numerical. The data type of MIN, MAX andSUM is the data type of the corresponding table field in the ABAP Dictionary. Aggregate

    expressions with the function AVG have the data type FLTP, and those with COUNT havethe data type INT4.

    Hint: the tool Iveused for demonstration replaces the field types of these aggregatefunctions for a more user friendly display (instead of the exponential notation).

    Example 13: Nesting subqueries

    Subqueries can be nested which means that you can put a subquery in the WHERE clause

    of a subquery. A maximum of ten SELECT statements are allowed within one OpenSQLquery (a SELECT statement may have maximum nine subqueries).

    Business requirement: exclude only customers who have cancelled bookings in Q1 of 2005and the language of the travel agency is English, where the cancellation was made. Pretty

    awkward, but I had to figure out something

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456761/20_other_group_functions.jpghttp://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456761/20_other_group_functions.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    21/30

    We can implement this logic using a nested subquery: we add this criteria to the WHEREclause of the outer subquery (select all agency numbers where the language is English).This is different from our previous subquery, because of the keyword we use for evaluatingit.

    Logical expressions for subqueries

    - EXISTS: this is what we have used in our first subquery. This returns TRUE if thesubquery returns any records (one or more) in its result set, otherwise this returns FALSE.

    - EQ, GT, GE, LT, LE: these operators can be used to compare a field with the result of thesubquery. If the subquery returns more than one row, obviously the database engine will notknow which one to use for comparison: a non-catchable exception will occur.

    - In order to use subqueries that return multiple rows, you either have to use the IN operator(checks if the field is equal to any of the values returned by the subquery) or one of the ALL,ANY, and SOME keywords together with EQ, GT, GE, LT or LE. These will influence thecomparison in a pretty self-explaining way: the comparison will be carried out with all therecords returned by the subquery, and the comparison will return TRUE if all (ALL) or atleast one (ANY, SOME) records return TRUE for the comparison. There is no differencebetween keywords SOME and ANY.

    What result do we expect? Since our outer subquery is used to filter out customers withcancelled bookings, a less restrictive subquery (achieved by the nested subquery) wouldmean more customers on our list. Practically: the less agencies we include in our search for

    cancellations, the more customers we get on the list.

  • 8/12/2019 A Complete Guide to OpenSQL Statements

    22/30

    Screenshot 15: nesting subqueries. As you can see, we actually have one more customeron our list, who cancelled his booking at an agency where the language is not English.

    Example 14: HAVING and GROUP BY in a subquery

    Business requirement: only exclude customers who have at least three cancellations(Lufthansa flight in Q1 of 2005 at an English speaking agency).

    Since we have to count the number of these bookings, we have to use group functionCOUNT and group the bookings by the customer ID. This way we get the number ofmatching bookings per customer. Then we simply add the HAVING clause to make sure weonly exclude customers having more than two cancellations from our main query.

    We can expect to have more customers in our result set, since we have a more restrictivesubquery that we use to filter out customers.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456762/21_nesting_subqueries.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    23/30

    Screenshot 16: using the GROUP BY and HAVING clauses in a subquery. As you can see,we have two more customers on our list (who have one or two matching cancelledbookings).

    Example 15: Letsextend the GROUP BY clause

    Business requirement: include only customers who have more than 10 bookings for thesame airline. It doesntmatter which, but it should be more than ten.

    So far we have counted all the bookings of the customers who satisfy all our criteria (forexample having more than 10 bookings of any airline). This could be like someone having 5bookings for Lufthansa, 5 for American Airlines and 2 for United Airlines (the total beinghigher than 10). Now we want to see something like 11 for Lufthansa.

    It is very simple to solve this by adding the airline code (CARRID) to the field list of our mainquery. Remember, the database engine will create groups of records based on all fieldslisted before the first group function in the field list (SELECT clause). If we add the airlinecode here, groups will be made per airline for each customer and the COUNT function willcount the number of bookings per customer and airline.

    What changes do we expect in our result set? There should be much less customers on ourlist, because they must have more than ten bookings for the same airline.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456763/22_having_gb_in_subquery.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    24/30

    Screenshot 17: adding the carrier ID to the GROUP BY clause (and the SELECT clause aswell).

    The result shows exactly this: we only have three (very loyal) customers who match ourselection criteria. Notice that the highest number of bookings is now only 12, while in theprevious example it was 19.

    Example 16: Going back to the LEFT OUTER JOIN

    In order to have some coordinates displayed in the result list, we make two changes:

    - change the WHERE condition of the main query: instead of checking the name of thecustomer and the airline code, we select customers from the US. This way we will havemuch more customers on our list (100 which is limited by the UP TO N ROWS addition) andsince they are from the US, we will see some region codes for the customers (coordinatesare maintained for the US regions).

    - remove the HAVING clause to include customers with less than 11 matching bookings.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456764/23_add_carrid_to_group_by.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    25/30

    Screenshot 18: first change: removing the check to have at least ten bookings.

    Screenshot 19: second change: select customers from the US.

    Now you can see again the behaviour of the LEFT OUTER JOIN: coordinates are filled forall records, where the region code is filled and coordinates are found for the region in tableGEOT005S.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456767/25_change_where_clause.jpghttp://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456766/24_remove_having_clause.jpghttp://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456767/25_change_where_clause.jpghttp://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456766/24_remove_having_clause.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    26/30

    Example 17: Using a selection table in the WHERE clause

    Selection tables are used to define complex selections on a field. They are mostly usedtogether with selection screens (using statement SELECT-OPTION). Any selection the usermakes on the user interface will be converted to a complex logical expression using the

    operators that we have worked with in this tutorial (EQ, GT, LE, GE, LT, NE, BETWEEN,NOT etc.). This conversion is made by the OpenSQL engine automatically.

    In order to compare the values of a table field with a selection table, you have to use theINoperator.

    Business requirement:only count bookings of Business Class and Economy Class (CandY)in a complex time range.

    Screenshot 20: performing complex selections using selection tables. Notice the INkeyword used as a comparison operator.

    Note: the tool used for this demonstration offers a UI to define the selection tables as on

    selection screens. Also, the generated WHERE clause is visible on the right side, next tothe selection tables R_SBOOK_FLDATE and R_SBOOK_CLASS.

    Example 18: The FORALL ENTRIES INconstruct

    This construct is widely used in ABAP and is similar to a table join in a way that it is used toread data from a table for records we already have (typically selected from another table or

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456768/26_use_range_tables.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    27/30

    returned by a Function Module). However, there are big differences between the twoconstructs.

    The FORALL ENTRIES IN internal tableconstruct allows you to use an internal table asthe basis of your selection, but not like a selection table from Example 17. If you use this

    addition, you can (actually, must) refer to the fields of the internal table in the FOR ALLENTRIES IN clause to perform comparison with the fields of the database table(s) beingread. Naturally the fields used in the comparison must have compatible data types.

    As this construct is ABAP specific, there is a mechanism that translates the OpenSQLcommand to one or more native SQL statements. Actually the WHERE clause(es) that willbe passed to the database engine will be generated based on the contents of the internaltable and the WHERE clause you define. There are several profile parameters thatinfluence this conversion, which you can check in SAP Note48230 - Parameterization forSELECT ... FOR ALL ENTRIES statement.

    The main difference between table joins and this construct is that table joins are carried outby the database server and all data is passed to the application server at once. On the otherhand, in case of a FOR ALL ENTRIES IN construct, the entire WHERE clause is evaluatedfor each individual row of the internal table. The result set of the SELECT statement is theunion of the result sets produced by the individual evaluations. It is very important to notethat duplicate records are automatically removed from the result set (but on the applicationserver and not on the database server).

    Syntactically, there is a difference that you have to use the -sign instead of the ~signbetween the internal table name and the field name of the internal table in the WHERE

    clause.

    Very imp or tant note: If the referenced internal table is empty, the entire WHERE clause isignored and all lines from the database are placed in the result set. Always make a checkon the internal table before executing a select query using this construct.

    Business requirement:read airline information for all airlines that appear on our list.

    How to implement this? We already have a SELECT statement from the previous example,so create a second SELECT statement using the FOR ALL ENTRIES IN construct. Simply

    add the carrier ID as a link into the WHERE clause (similar to the join condition in case oftable joins) and thatsit.

    http://service.sap.com/sap/support/notes/48230http://service.sap.com/sap/support/notes/48230http://service.sap.com/sap/support/notes/48230http://service.sap.com/sap/support/notes/48230http://service.sap.com/sap/support/notes/48230http://service.sap.com/sap/support/notes/48230
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    28/30

    Screenshot 21: using the FORALL ENTRIES IN internal tableconstruct.

    Note: the tool Iveused for demonstration uses outer_tableas the name of the internaltable. The contents of it are coming from the select query of example 17.

    Note: As of release 6.10, the same internal table can be specified after FOR ALL ENTRIESand after INTO. However, be careful because in this case all fields of the internal table thatare not filled by the SELECT query will be cleared.

    Note: performance-wise there are endless discussions on SCN if a table join or the FORALL ENTRIES IN construct is better. It really depends on the buffering settings of the tablesyou select from, the fields you use for joins and selections, the indexes that are available,the number of records in both tables, profile parameters of the SAP system etc. In general I

    prefer joins since it is a toolthat is designed especially for the purpose of reading datafrom multiple tables at the same time and it is done on the database layer. Of course certainsituations are against a table join. Also, you have no choice if you use a BAPI/FunctionModule/Class method to get records from the database, since obviously in that case youcannot use a table join but you have to use the FOR ALL ENTRIES IN construct.

    Other keywords

    SINGLE and FOR UPDATE

    If you use the SINGLE addition, the result set will contain maximum one record. If theremaining clauses of the SELECT statement would return more than one line, only the firstwill be returned.

    http://scn.sap.com/servlet/JiveServlet/showImage/38-107658-456769/27_for_all_entries.jpg
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    29/30

    The FOR UPDATE addition can be used only with the SINGLE addition, which you can useto set an exclusive lock for the selected record. However, this is rarely used and I alsoprefer using lock function modules separately.

    Note: The addition SINGLE is not permitted in a subquery and the ORDER BY clause cannot be used together with it.

    CLIENT SPECIFIED

    This addition switches off the automatic client handling of Open SQL. When using theaddition CLIENT SPECIFIED, the first column of the client-dependent database tables canbe specified in the WHERE and ORDER BY clauses.

    BYPASSING BUFFER

    This addition causes the SELECT statement to bypass SAP buffering and to read directlyfrom the database and not from the buffer on the application server.

    ENDSELECT

    A SELECT statement may retrieve database records one by one (functioning as a loopusing keyword INTO), or together at once (this is called arrayfetchand is used withkeyword INTO TABLE/APPENDING TABLE). In the first case the ENDSELECT statement

    closes the loop started with SELECT. Both constructs retrieve the same result.

    Out of scope for this blog post

    Database hints

    Basically using hints is used to specify how the database engine should execute our query.If you omit this, then the DB engine will use its own optimizer to determine the best strategyto execute the SELECT statement. Using hints to override this default strategy is quitefrequent outside of SAP, but it is seldom used with ABAP.

    One reason is that not many developers know that it is possible to use hints with OpenSQLstatements (not only with native ones). Also, there are certain drawbacks (problems duringDB upgrade or change of DB server) and there is more possibility for human errors.

    There is a very good overview of database hints in SAP Note129385 - Database hints inOpen SQL

    http://service.sap.com/sap/support/notes/129385http://service.sap.com/sap/support/notes/129385http://service.sap.com/sap/support/notes/129385http://service.sap.com/sap/support/notes/129385http://service.sap.com/sap/support/notes/129385http://service.sap.com/sap/support/notes/129385
  • 8/12/2019 A Complete Guide to OpenSQL Statements

    30/30

    Dynamic token specification

    It is possible to assemble OpenSQL statements during runtime. So instead of coding a

    static SELECT statement, you can use character-type variables to hold the SELECT,FROM, WHERE etc. clauses. This may come handy in certain cases, but it hasdisadvantages regarding performance, maintainability and code readability. Also, there arecertain SAP release dependent restrictions on the allowed syntax elements. There aresome nice materials on SCN and other sites that deal with this topic.

    Conclusion

    As you can see, even though Open SQL is a very limited subset of the modern SQLlanguage, it still allows you to execute quite complex queries. In most cases the wholebusiness logic of a complex report cannot be mapped into a single select query, however if

    you know what possibilities you have, you can write much more elegant and compactprogram code with better performance.

    Thanks for reading and have fun using Open SQL.