Using Data from a Table or View

Objectives

After completing this lesson, you will be able to:
  • Write simple database queries using SQL‘s SELECT statement and project columns.
  • Use built-in functions and CASE expressions in column lists to calculate column values.
  • Avoid duplicates in SELECT statement result sets.
  • Restrict the result set using the WHERE clause.
  • Explain the EXISTS and IN Predicates.
  • Ensure a specific order in result sets.
  • Limit results sets to a given number of rows and browse through result sets.

Overview of the SELECT Statement

The SELECT statement is an SQL statement that is used to read data from a database table or view. The SELECT statement is the central construct for read access to data, of the Data Manipulation Language.

A SELECT statement must contain a SELECT and a FROM clause, and may contain WHERE, GROUP BY, HAVING, and ORDER BY clauses. In special circumstances, other clauses may be added to the SELECT, some of which will be discussed in later lessons.

Below is a code block showing a partially-specified SELECT statement with mandatory and optional clauses:

Code Snippet
123456
SELECT <expression>, <expression>, COUNT(*) FROM <data_source> WHERE <condition> GROUP BY <expression>, <expression> HAVING <group_condition> ORDER BY <expression> ASC, <expression> DESC;

The Sample Data Model

The examples used in the lessons and figures of this course are based on a fictional car registration office.

Example: Registration Office

  • The database of a fictional registration office serves as the basis for examples.

  • The tables in this database have been specifically tailored to this course and are not an example of good database design.

  • The officials working in the fictional registration office have a manager.

  • Each vehicle is registered for exactly one owner (or is unregistered).

  • There is a list of vehicles that have been reported stolen.

  • Owners, who have at least three vehicles registered, are assigned to one or multiple contacts.

Registration office example showing the five different tables, as Official, Contact, Owner, Car, and Stolen, with respective fields.

The following shows the content of the Official database table as an example.

The Official Table

OfficialPNrNameOvertimeSalaryManager
 P01Mr A10A09P04
P02Mr B10A10P04
P03Ms C20A09P04
P04Ms DNULLA12P09
P05Mr E10A08P08
P06Mr F18A09P09
P07Ms G22A11P08
P08Ms HNULLA13P09
P09Mr INULLA14NULL

The Owner database table contains the information about the car owners. Note that owners who are people have a birthday, but owners that are companies do not.

The Owner Table

OwnerOwnerIDNameBirthdayCity
 H01Ms T20.06.1934Wiesloch
H02Ms U11.05.1966Hockenheim
H03SAP AGNULLWalldorf
H04HDM AGNULLHeidelberg
H05Mr V21.04.1952Leimen
H06Ms W01.06.1957Wiesloch
H07IKEANULLWalldorf
H08Mr X30.08.1986Walldorf
H09Ms Y10.02.1986Sinsheim
H10Mr Z03.02.1986Ladenburg

The Contact database table relates a car owner owning more than two cars to the officials who are the respective contact persons.

The Contact Table

ContactPersNumberOwnerID
 P01H03
P01H04
P01H07
P04H03
P04H04
P08H04
P08H07
P09H03

Cars

Database table of Cars.

Stolen Cars

Database table of Stolen Cars

Registration Office and EU

A new (fictional) European Union directive requires that the information about which vehicle is registered to which owner has to be stored in a central transnational database.

The vehicle identification number (CarID) is unique across the EU, but not the Owner ID.

Owner_EU and Car_EU database tables with respective fields, where Country and Owner fields of Car_EU are shown as connected to Country and OwnerID of Owner_EU.

Owner (EU-Wide)

Database table of Owner (EU-Wide).

Cars (EU-Wide)

Database table of Cars (EU-Wide).

Relationships Between the Tables

Diagram showing the relationships between the tables.

The SELECT Statement in its Most Simple Form

The SELECT clause specifies the Projection List. The Projection List defines which columns to read from the data or which columns to include in the result set of the SELECT statement.

Multiple Columns in Projection List

You can specify multiple columns in the projection list:

Code Snippet
12
SELECT PNr, Name, Salary FROM Official;
PNRNAMESalary
P01Mr AA09
P02Mr BA10
P03Ms CA09
P04Ms DA12
P05Mr EA08
P06Mr FA09
P07Mr GA11
P08Mr HA13
P09Mr IA14

Sequence of Columns in the Projection List

The sequence of the columns in the projection list is relevant:

Code Snippet
12
SELECT PNr, Name FROM Official;
PNRNAME
P01Mr A
P02Mr B
P03Ms C
P04Ms D
Code Snippet
12
SELECT Name, PNr FROM Official;
NAMEPNR
Mr AP01
Mr BP02
Ms CP03
Ms DP04

All Columns Asterisk in Projection List

An asterisk (*) in the projection list represents all columns:

Code Snippet
12
SELECT * FROM Official;
PNRNAMEOVERTIMESALARYMANAGER
P01Mr A10A09P04
P02Mr B10A10P04
P03Mr C20A09P04
P04Mr D?A12P09

Note

Although frequently convenient, the use of * as an all columns alias is discouraged; examining the code does not clearly indicate what columns will be returned without executing the query, and if the table changes structure (adding or removing columns) the result may or may not change as expected depending on where the SELECT is used.

The following options are also supported:

  • You can include a single column in the projection list.

  • You can include the same column in the projection list repeatedly.

  • You can combine using the asterisk and explicitly named columns.

  • You can use the asterisk repeatedly in the projection list.

We do not recommend using the last three options because each makes the result set difficult to understand and work with.

Naming Columns of the Result Set

It is possible to rename the columns of the result set so that they differ from the column names in the table.

Note

Renaming columns in the SELECT clause has no effect on the table from which they are selected. It only changes the result set returned.

Renaming Columns in the Projection

You can rename result columns:

Code Snippet
12
SELECT PNr AS PersNumber, Salary AS "Salary Group" FROM Official;
PERSNUMBERSalary Group
P01A09
P02A10
P03A09
P04A12

Column names not enclosed in quotation marks are converted to upper case. A column name has to be enclosed in quotation marks if one of the following applies:

  • The column name should not be converted to upper case but should be kept exactly as spelled in your statement.

  • The column name contains a space, a punctuation mark, a colon, or any other special character.

Note

This rule also applies to the names of the original database tables and their columns; the SQL parser converts names not enclosed in quotation marks to upper case. It then performs a case-sensitive search for the corresponding database objects.

The keyword AS is optional.

You can use column names of the table selected from to rename other columns of the result set, for example, to exchange column names.

Reusing Existing Column Names for Other Columns

You can use existing column names for (re)naming of result columns:

Code Snippet
12
SELECT PNr Salary, Salary PNr FROM Official;
SALARYPNR
P01A09
P02A10
P03A09
P04A12
P05A08
P06A09
P07A11
P08A13
P09A14

Note

Obviously, displaying the personnel numbers and salary bands underneath headings for the other column would be a bad choice in practice. This example is merely to show what could be done, not to show a best practice.

The SELECT Clause: Calculated Columns

The SELECT clause can also contain columns with values that are computed dynamically, typically based on the values of other columns.

In the most simple form, these calculated columns can be literal values. Both string and numerical literals are supported.

Literal Values in the SELECT Clause

You can generate additional "literal" result columns.

The additional result column can have a string or a numeric type:

Code Snippet
12
SELECT 'The working week of', Name, 'amounts to', 40, 'hours.' FROM Official;
'The working week of'NAME'amounts to'40'hours'.
The working week ofMr Aamounts to40hours.
The working week ofMr Bamounts to40hours.
The working week ofMr Camounts to40hours.
The working week ofMr Damounts to40hours.
The working week ofMr Eamounts to40hours.
The working week ofMr Famounts to40hours.
The working week ofMr Gamounts to40hours.
The working week ofMr Hamounts to40hours.
The working week ofMr Iamounts to40hours.

Note

String values are enclosed in single quotes. This can lead to confusion if column names are enclosed in quotation marks as well.

Numerical values are not enclosed in quotes.

Built-In Table DUMMY

The projection list can even comprise one or more literal values only. Note that the result set still contains as many records, all comprising the same literal values only, as the table select from contains. If your intent is to select a single literal record, you can use the built-in table DUMMY.

Code Snippet
12
SELECT 'Good Morning!' FROM DUMMY;
'Good Morning!'
Good Morning!

The DUMMY table contains one column and one row:

Code Snippet
12
SELECT * FROM DUMMY;
DUMMY
X

Calculated Columns

The projection list can have computed columns.

If a NULL value is used in an arithmetic operation, the result is also a NULL value:

Code Snippet
12
SELECT Name, Overtime * 60 FROM Official;
NAMEOVERTIME*60
Mr A600
Mr B600
Mr C1200
Mr D?
Mr E600
Mr F1080
Mr G1320
Mr H?
Mr I?

Note

NULL values will be discussed in the next lesson. For now, they represent absent or unknown values and are shown in the output of these examples with the placeholder "?". In this example, the OVERTIME for Mr D, Mr H, and Mr I are unknown, so the value multiplied by 60 is likewise unknown.

Naming Calculated Columns

You can explicitly name computed result columns:

Code Snippet
12
SELECT Name, Overtime * 60 AS Overminutes FROM Official;
NAMEOVERMINUTES
Mr A600
Mr B600
Mr C1200
Mr D?

Note

This is the first instance of a very useful aspect of the SQL language: as a general rule, you can combine any number of valid syntactical structures together. In this case, the calculation syntax is combined with the column result rename syntax.

Functions

SAP HANA supports using functions to calculate columns of the projection list. Different functions are supplied for different data types of the input columns and values, and users may create their own functions.

When were vehicle owners first allowed to drive a car in Germany?

Code Snippet
12
SELECT Name, ADD_YEARS(Birthday, 18) AS "18th Birthday" FROM Owner;
NAME18th Birthday
Ms T1952-06-20
Ms U1984-05-11
SAP AG?
HDM AG?
Mr V1970-04-21
Ms W1975-06-01
IKEA?
Mr X2004-08-30
Ms Y2004-02-10
Ms Z2004-02-03

Function Calls can be Nested

Function calls can be nested.

On which day is the owner’s 18th birthday?

Code Snippet
12345678
SELECT Name, DAYNAME ( ADD_YEARS (Birthday, ROUND(ABS(-18.2)) ) ) AS Weekday FROM Owner;
NAMEWEEKDAY
Ms TFRIDAY
Ms UFRIDAY
SAP AG?
HDM AG?
Mr VTUESDAY
Ms WSUNDAY
IKEA?
Mr XMONDAY
Ms YTUESDAY
Mr ZTUESDAY

Built-In Functions

Currently there are 248 built-in functions available, grouped into 12 categories (for example, aggregate functions, array functions, datatype functions). Functions can be very specific, such as ADD_WORKDAYS():

Code Snippet
123456789
ADD_WORKDAYS( <factory_calendar_id>, <start_date>, <workdays> [, <source_schema> [, <table_name_suffix>, [, <client> ] ] ] )

SPS07 and later allow the usage of factory and holiday calendar for ADD_WORKDAYS() and WORKDAYS_BETWEEN() functions. The parameters <table_name_suffix> and <client> have been added to these functions. A prerequisite for this is that the day collections are provided in TFACS or structure-like tables.

TFACS Example

Built-in function ADD_WORKDAYS TFACS Example

-- Germany Bavaria 2023

Code Snippet
1234567891011121314
insert into TFACS values ('BY', '2023’, '0111100011111001111100111110011’, -- january '1110011111001111100111110011’, -- february '1110011111001111100111110011111’, -- march '001111000011110011111001111100’, -- april '0111100111110011101001111100011’, -- may '110011101001111100111110011111’, -- june '0011111001111100111110011111001’, -- july '1111001111100101110011111001111’, -- august '100111110011111001111100111110’, -- september '0101110011111001111100111110011’, -- october '011001111100111110011111001111’, -- november '1001111100111110011111000011100’ -- december , ' ', ' ', ' ' , ' ');

Add Workdays Example

What calendar day was the first workday of the year 2023 in Bavaria?

Code Snippet
123
SELECT ADD_WORKDAYS ('BY', '20230101', 5 ) AS "Workday" FROM DUMMY;
Workday
2023-01-09

…and in North-Rhine Westphalia?

Code Snippet
123
SELECT ADD_WORKDAYS ('NRW', '20230101', 5) AS "Workday" FROM DUMMY;
Workday
2023-01-06

Selection of Functions Supported by SAP HANA

SAP HANA supports a rich list of built-in function. The following is only a minor selection.

FunctionExplanation
ADD_YEAR(<date>, <number>)Adds a <number> of years to the specified <date>
CURRENT_DATE()Determines the current date
ABS(<number>)Determines the absolute value
ROUND(<number>)Rounds the <number>
SQRT(<number>)Determines the square root of <number>
UPPER(<string>)Converts the <string> to upper case
SUBSTR(<string>,<start>,<len>)Extracts a substring of <string>
CONCAT(<string>,<string>)Concatenates two strings. Equivalent to the binary operator ||.
COALESCE(<expressions>))Returns the result of the first element of the list of <expressions> that does not evaluate to NULL.

See the SAP HANA SQL reference available on the SAP Help Portal for the full list of supported built-in functions. http://help.sap.com/hana_platform#section6

You can also create scalar user-defined functions and use them in the same way as built-in functions.

The CASE Expression

A special way of calculating column values is using a CASE expression. This expression allows you to determine a column value based on conditions, in other words, to include an IF-THEN-ELSE type of logic in the projection list.

Case Expression: Basic Form

The projection list can contain columns that are based on a CASE expression.

These columns can be named explicitly:

Code Snippet
1234567
SELECT *, CASE WHEN HP < 120 THEN 'low' WHEN HP >= 120 AND HP < 180 THEN 'medium' ELSE 'high' END AS Rating FROM Car;

Case Expression: Result

CARIDPLATENUMBERBRANDCOLORHPOWNERRATING
F01HD-V 106Fiatred75H06low
F02HD-VW 4711VWblack120H03medium
F03HD-JA 1972BMWblue184H03high
F04HD-AL 1002Mercedeswhite136H07medium
F05HD-MM 3206Mercedesblack170H03medium
F06HD-VW 1999Audiyellow260H05high
F07HD-ML 3206Audiblue116H03low
F08HD-IK 1002VWblack160H07medium
F09HD-UP 13Skodared105H02low
F10HD-MT 507BMWblack140H04medium
F11HD-MM 208BMWgreen184H02high
F12HD-XY 4711Skodared105H04low
F13HD-IK 1001Renaultred136H07medium
F14HD-MM 1977Mercedeswhite170H03medium
F15HD-MB 3030Skodablack136H03medium
F16?Opelgreen120?medium
F17HD-Y 333Audiorange184H09high
F18HD-MQ 2006Renaultred90H03low
F19HD-VW 2012VWblack125H01medium
F20?Audigreen184?high

Case Expression: Case not Handled

If a CASE expression does not correspond to any of the listed cases, a NULL value is returned:

Code Snippet
12345678910
SELECT CarID, CASE Color WHEN 'red' THEN 'FF0000' WHEN 'green' THEN '00FF00' WHEN 'yellow' THEN 'FFFF00' WHEN 'blue' THEN '0000FF' WHEN 'white' THEN 'FFFFFF' WHEN 'black' THEN '000000' END AS Color FROM Car;
CARIDCOLOR
F01FF0000
F02000000
F030000FF
F04FFFFFF
F05000000
F06FFFF00
F070000FF
F08000000
F09FF0000
F10000000
F1100FF00
F12FF0000
F13FF0000
F14FFFFFF
F15000000
F1600FF00
F17?
F18FF0000
F19000000
F2000FF00

Case Expression: Using Columns in the THEN and ELSE Branches

Both the THEN and the ELSE branch can contain references to table columns:

Code Snippet
123456789101112
SELECT CarID, CASE WHEN PlateNumber IS NOT NULL THEN PlateNumber ELSE 'The Car is not registered!' END AS PlateNumber, CASE Brand WHEN 'Mercedes' THEN 'Mercedes-Benz' WHEN 'VW' THEN 'Volkswagen' ELSE Brand END AS Brand, Color, HP FROM Car;

Case Expression: Result

CARIDPLATENUMBERBRANDCOLORHP
F01HD-V 106Fiatred75
F02HD-VW 4711Volkswagenblack120
F03HD-JA 1972BMWblue184
F04HD-AL 1002Mercedes-Benzwhite136
F05HD-MM 3206Mercedes-Benzblack170
F06HD-VW 1999Audiyellow260
F07HD-ML 3206Audiblue116
F08HD-IK 1002Volkswagenblack160
F09HD-UP 13Skodared105
F10HD-MT 507BMWblack140
F11HD-MM 208BMWgreen184
F12HD-XY 4711Skodared105
F13HD-IK 1001Renaultred136
F14HD-MM 1977Mercedes-Benzwhite170
F15HD-MB 3030Skodablack136
F16The Car is not registered!Opelgreen120
F17HD-Y 333Audiorange184
F18HD-MQ 2006Renaultred90
F19HD-VW 2012Volkswagenblack125
F20The Car is not registered!Audigreen184

Note

When referencing a column as with BRAND in this example, only single-term equality tests are supported. The inequality and compound tests shown in the first example are not possible.

Eliminating Duplicates in Result Sets

An important difference between SQL and the Relational Database Model is that SQL is multi-set oriented, which allows for duplicate entries in result sets. However, you won’t notice this as long as the database table you select from has a primary key, and once you select all of the columns.

No Duplicates with Primary Key

A table with an enforced primary key does not contain duplicates.

Code Snippet
12
SELECT * FROM Car;
CARIDPLATENUMBERBRANDCOLORHPOWNER
F04HD-AL 1002Mercedeswhite136H07
F05HD-MM 3206Mercedesblack170H03
F09HD-UP 13Skodared105H02
F14HD-MM 1977Mercedeswhite170H03
F15HD-MB 3030Skodablack136H03

If you project a table and don’t include the full primary key, duplicate entries can result.

Duplicates by Projection

Duplicates can occur when a key column is not included in the projection list:

Code Snippet
12
SELECT Brand FROM Car;
BRAND
Mercedes
Mercedes
Skoda
Mercedes
Skoda

Duplicate Elimination using DISTINCT

In most cases, this is not intended or practical, as there is no way to distinguish the duplicate entries from each other in the result set. This is why duplicate entries can be removed explicitly using the keyword DISTINCT. Note that duplicates are not removed by default to speed up data retrieval.

The keyword DISTINCT ensures that the result table contains no duplicates:

Code Snippet
12
SELECT DISTINCT Brand FROM Car;
BRAND
Fiat
VW
BMW
Mercedes
Audi
Skoda
Renault
Opel

Duplicate Elimination: Treatment of NULL Values

NULL values ​​are treated in duplicate elimination as normal values.

The result table contains (at most) one row that consists entirely of NULL values:

Code Snippet
12
SELECT DISTINCT Overtime FROM Official;
OVERTIME
10
20
?
18
22

DISTINCT Eliminates Duplicates in Multi-Column Result Set

If a projection list contains multiple columns, DISTINCT always refers to the combination of all these columns:

Code Snippet
12
SELECT DISTINCT Brand, Color FROM Car;
BRANDCOLOR
Mercedeswhite
Mercedesblack
Skodared
Skodablack

In principle, you could always include the DISTINCT keyword in the SELECT statement to be sure you never get duplicates. This is because DISTINCT is compatible with using an asterisk in the projection list. Note, however, that using DISTINCT comes at a small performance penalty.

The WHERE Clause

The WHERE clause is used to select a subset of rows from the data source based on a specified condition. Only the rows matching the condition are returned.

The WHERE clause is used to filter rows.

It is used to extract only those rows that fulfill a specified criterion.

Code Snippet
123
SELECT PlateNumber, Brand, Color FROM Car WHERE Brand = 'BMW';
PLATENUMBERBRANDCOLOR
HD-JA 1972BMWblue
HD-MT 507BMWblack
HD-MM 208BMWgreen

You can reference a column in the WHERE clause that is not included in the projection list.

Code Snippet
123
SELECT Brand, Color FROM Car WHERE HP >= 170;
BRANDCOLOR
BMWblue
Mercedesblack
Audiyellow
BMWgreen
Mercedeswhite
Audiorange
Audigreen

Condition expressions in SQL are very similar to condition expressions in programming languages such as ABAP, Java, and so on. The columns of the data source take over the roles of variables used in these languages.

  • A condition can refer to string-like or to numeric columns. The columns used in the condition do not have to be included in the projection list.

  • Atomic conditions can be combined to complex and nested conditions using the usual logical operators AND, OR, and NOT. Parentheses can be used to control the order of operations.

  • A condition can make use of functions, including nested functions.

An atomic condition typically contains a comparison operator. The usual comparison operators =, <>, <, <=, >, and >= are supported. However, SQL supports a few additional comparison operators.

Comparison Operator IS NULL

You can check for the presence of NULL values in the WHERE clause:

Code Snippet
123
SELECT CarID, Brand, Color FROM Car WHERE PlateNumber IS NULL;
CARIDBRANDCOLOR
F16Opelgreen
F20Audigreen

Comparison Operator IS NOT NULL

Likewise, you can check for the absence of NULL values in the WHERE clause:

Code Snippet
123
SELECT CarID, Brand, Color FROM Car WHERE PlateNumber IS NOT NULL;
CARIDBRANDCOLOR
F01Fiatred
F02VWblack
F03BMWblue
F04Mercedeswhite
F05Mercedesblack
F06Audiyellow
F07Audiblue
F08VWblack
F09Skodared
F10BMWblack
F11BMWgreen
F12Skodared
F13Renaultred
F14Mercedeswhite
F15Skodablack
F17Audiorange
F18Renaultred
F19VWblack

Comparison Operator IN

You can check if values are included in a value list.

Code Snippet
123
SELECT Brand, Color FROM Car WHERE Color IN ('red', 'blue', 'orange');
BRANDCOLOR
Fiatred
BMWblue
Audiblue
Skodared
Skodared
Renaultred
Audiorange
Renaultred

Comparison Operator BETWEEN and AND

You can check if values are included in an interval.

Code Snippet
123
SELECT PlateNumber, Brand, Color, HP FROM Car WHERE HP BETWEEN 140 AND 170;

Note

The lower bound of a BETWEEN comparison must come before the upper bound. The results are inclusive of the endpoints.
PLATENUMBERBRANDCOLORHP
HD-MM 3206Mercedesblack170
HD-IK 1002VWblack160
HD-MT 507BMWblack140
HD-MM 1977Mercedeswhite170

Comparison Operator LIKE

You can use search patterns in the WHERE clause.

Code Snippet
123
SELECT PlateNumber, Brand, Color, HP FROM Car WHERE PlateNumber LIKE '%MM%';
PLATENUMBERBRANDCOLORHP
HD-MM 3206Mercedesblack170
HD-MM 208BMWgreen184
HD-MM 1977Mercedeswhite170

Wildcards in the LIKE Predicate

Wildcard searching is done with the LIKE predicate, not the equals (=) predicate. The wildcard character % (percentage sign) represents any string containing zero, one, or multiple characters. The wildcard character _ (underscore) represents any single character.

WHERE MyColumn LIKE 'M%'String starting with "M"
WHERE MyColumn LIKE 'M _'String of two characters starting with "M"
WHERE MyColumn LIKE '%M'String ending with "M"
WHERE MyColumn LIKE '%M%'String containing "M"
WHERE MyColumn LIKE '_ _ _'String of three characters
WHERE MyColumn LIKE '_ _ _ _T_M%'String with "T" in the fifth and "M" in the seventh position

Escaping Wildcards in the LIKE Predicate

If you want to search for the percentage sign (%) or underscore (_) itself, you have to place an ESCAPE character in front. You can choose the ESCAPE character (with some restrictions).

LIKE '$%%' ESCAPE '$'String starting with a percentage sign
LIKE '$_ _' ESCAPE '$'String of two characters starting with an underscore
LIKE '%$%' ESCAPE '$'String ending with a percentage sign
LIKE '%$%%' ESCAPE '$'String containing a percentage sign
LIKE '%$_$%%' ESCAPE '$'String containing an underscore followed by a percentage sign
LIKE '_ _ _ _ $%_ $ _%' ESCAPE '$'"%" in the fifth and "_" in the seventh position

A Complex WHERE Clause

  • The license plate started with "HD" for Heidelberg.
  • I'm sure I saw an "M".
  • I clearly remember the digits "2" and "6".
  • The "2" was definitely left of the "6".
  • Between the "2" and the "6" was exactly one digit.
  • It was neither Skoda, nor a VW.
  • The car was blue or green.
Code Snippet
123456
SELECT * FROM Car WHERE PlateNumber LIKE 'HD-%M% %2_6%' AND Brand <> 'Skoda' AND Brand <> 'VW' AND (Color = 'blue' OR Color = 'green');
CARIDPLATENUMBERBRANDCOLORHPOWNER
F07HD-ML 3206Audiblue116H03

Operator Precedence

The operators have the precedence indicated by the table below:

PrecedenceOperatorExplanation
Highest()parentheses
 unary minus
 *, /multiplication, division
 +, ‒addition, subtraction
 

=, <, <=, >, >=, <>,

IS NULL, LIKE, BETWEEN

comparison
 NOTlogical negation
 ANDconjunction
LowestORdisjunction

EXISTS and IN

EXISTS and IN Predicates

Both the EXISTS keyword as well as the IN keyword are predicate keywords. This means that in combination with other keywords, the developer is able to create an expression to determine whether something is TRUE, FALSE, or UNKNOWN.

  • EXISTS allows the developer to evaluate if a result set has any entries.
  • IN allows the developer to evaluate if a given value matches one of a enumerated set of values.

In the case of an expression using EXISTS, the expression will return TRUE if the query contained in the expression returns a minimum of one record (in other words, not an empty result set). Otherwise, the expression will return FALSE (in other words, an empty result set). EXISTS can be used in IN and WHILE expressions (to be discussed later).

In the case of an expression containing an IN, the expression will return TRUE if the value on the left side of the IN matches at least one of a defined list of values on the right side of the IN. Otherwise, the expression will return FALSE. The value on the left side of the IN can be the result of a subquery.

In addition, a tuple (multiple values to match) can be used, that is, (city, country) IN ((‘Los Angeles’,’UnitedStates’),(‘London’,’England’));). IN can be used in expressions formulated with conditional logical such as IF and WHILE (to be discussed later) as well as WHERE clauses.

The ORDER BY Clause

By default, the result returned by a query in SAP HANA has no defined and no reliable sort order. Executing the same query repeatedly can result in different sort orders.

Note

Query results in the SAP HANA database are not sorted by primary key by default. There is no defined or reliable default sort order.

You can use the ORDER BY clause to explicitly specify the sort order of the result set. This way you can get a reliable sort order.

The ORDER BY Clause

The result table can be sorted by a specific column:

Code Snippet
123
SELECT Brand, Color FROM Car ORDER BY Brand;
BRANDCOLOR
Audiyellow
Audiblue
Audiorange
Audigreen
BMWblue
BMWblack
BMWgreen
Fiatred
Mercedeswhite
Mercedesblack
Mercedeswhite
Opelgreen
Renaultred
Renaultred
Skodared
Skodared
Skodablack
VWblack
VWblack
VWblack

Descending Sort Order

A descending sorting is possible:

Code Snippet
123
SELECT Brand, Color FROM Car ORDER BY Brand DESC;
BRANDCOLOR
VWblack
VWblack
VWblack
Skodablack
Skodared
Skodared
Renaultred
Renaultred
Opelgreen
Mercedeswhite
Mercedesblack
Mercedeswhite
Fiatred
BMWgreen
BMWblack
BMWblue
Audigreen
Audiorange
Audiblue
Audiyellow

Ascending Sort Order

Although ascending order is assumed, you may use the optional keyword ASC to make sort order explicitly clear:

Code Snippet
123
SELECT Brand, Color FROM Car ORDER BY Brand ASC;
BRANDCOLOR
Audiyellow
Audiblue
Audiorange
Audigreen
BMWblue
BMWblack
BMWgreen
Fiatred
Mercedeswhite
Mercedesblack
Mercedeswhite
Opelgreen
Renaultred
Renaultred
Skodared
Skodared
Skodablack
VWblack
VWblack
VWblack

Sorting by a Column not in the Result

The sorting can be applied using a column that does not appear in the projection list:

Code Snippet
123
SELECT Brand, Color FROM Car ORDER BY PlateNumber;
BRANDCOLOR
Opelgreen
Audigreen
Renaultred
Mercedeswhite
VWblack
BMWblue
Skodablack
Audiblue
Mercedeswhite
BMWgreen
Mercedesblack
Renaultred
BMWblack
Skodared
Fiatred
Audiyellow
VWblack
VWblack
Skodared
Audiorange

Sorting by Multiple Columns

You can sort using a combination of columns:

Code Snippet
123
SELECT Brand, Color FROM Car ORDER BY Brand ASC, Color DESC;
BRANDCOLOR
Audiyellow
Audiorange
Audigreen
Audiblue
BMWgreen
BMWblue
BMWblack
Fiatred
Mercedeswhite
Mercedeswhite
Mercedesblack
Opelgreen
Renaultred
Renaultred
Skodared
Skodared
Skodablack
VWblack
VWblack
VWblack

Referencing Columns by Position

Instead of the column names in the ORDER BY clause, the column numbers (based on the projection list) can be used:

Code Snippet
123
SELECT Brand, Color FROM Car ORDER BY 1 ASC, 2 DESC;
BRANDCOLOR
Audiyellow
Audiorange
Audigreen
Audiblue
BMWgreen
BMWblue
BMWblack
Fiatred
Mercedeswhite
Mercedeswhite
Mercedesblack
Opelgreen
Renaultred
Renaultred
Skodared
Skodared
Skodablack
VWblack
VWblack
VWblack

Sorting and Column Renaming

If result columns are named explicitly, you can refer to the new name for sorting:

Code Snippet
123
SELECT Brand AS Manufacturer, Color FROM Car ORDER BY Manufacturer ASC, Color DESC;
MANUFACTURERCOLOR
Audiyellow
Audiorange
Audigreen
Audiblue
BMWgreen
BMWblue
BMWblack
Fiatred
Mercedeswhite
Mercedeswhite
Mercedesblack
Opelgreen
Renaultred
Renaultred
Skodared
Skodared
Skodablack
VWblack
VWblack
VWblack

Sorting by Calculated Columns

You can sort based on calculated values.

Sorting criteria: How much is the power below 200 kW?

Code Snippet
123
SELECT CarID, Brand, HP FROM Car ORDER BY 200 - HP / 1.36 ASC;
CARIDBRANDHP
F06Audi260
F03BMW184
F11BMW184
F17Audi184
F20Audi184
F05Mercedes170
F14Mercedes170
F08VW160
F10BMW140
F04Mercedes136
F13Renault136
F15Skoda136
F19VW125
F02VW120
F16Opel120
F07Audi116
F09Skoda105
F12Skoda105
F18Renault90
F01Fiat75

You can also use functions in the expression in the ORDER BY clause.

The TOP, LIMIT, and OFFSET Clauses

You can use the TOP N clause as part of the SELECT clause to specify that the result set should contain at most N rows.

Limiting the Result Set to a Maximum Number of Rows

You can limit the number of rows to be included in the query result to a maximum number.

What are the ten most powerful vehicles (based on horsepower)?

Code Snippet
123
SELECT TOP 10 CarID, Brand, Color, HP FROM Car ORDER BY 4 DESC;
CARIDBRANDCOLORHP
F06Audiyellow260
F20Audigreen184
F17Audiorange184
F11BMWgreen184
F03BMWblue184
F14Mercedeswhite170
F05Mercedesblack170
F08VWblack160
F10BMWblack140
F15Skodablack136

TOP N Clause can be Combined with DISTINCT

You can combine the TOP N clause with the keyword DISTINCT.

What are the seven highest HP values?

Code Snippet
123
SELECT TOP 7 DISTINCT HP FROM Car ORDER BY 1 DESC;
HP
260
184
170
160
140
136
125

TOP N Clause with Fewer Rows than N

No error is thrown if you request more rows than are available. The result set will not be filled with additional, artificial rows.

570 different colors are requested:

Code Snippet
12
SELECT TOP 570 DISTINCT Color FROM Car;
COLOR
red
black
blue
white
yellow
green
orange

TOP N Clause with N=0

It is possible to request zero result rows. In this case, the result set does not contain any rows.

Zero colors are requested:

Code Snippet
12
SELECT TOP 0 Color FROM Car;
COLOR
- - - - -

The LIMIT Clause as an Alternative to TOP N

The TOP N clause allows you to limit the result set to a specified maximum number of rows, but it does not allow you to retrieve the "next" N rows. To browse through a result in a page-by-page way, you can use the LIMIT and OFFSET clauses.

You can use the LIMIT clause as an alternative to the TOP N clause. The LIMIT clause comes at the very end of the SELECT statement.

What are the five most powerful vehicles (based on horsepower)?

Code Snippet
1234
SELECT * FROM Car ORDER BY HP DESC LIMIT 5;
CARIDPLATENUMBERBRANDCOLORHPOWNER
F06HD-VW 1999Audiyellow260H05
F20?Audigreen184?
F17HD-Y 333Audiorange184H09
F11HD-MM 208BMWgreen184H02
F03HD-JA 1972BMWblue184H03

Combine LIMIT and OFFSET to Browse through a Result Set

The LIMIT clause can be combined with the OFFSET clause to skip records. This allows you to read result sets page by page across multiple queries.

What are the next five most powerful vehicles (based on horsepower)?

Code Snippet
12345
SELECT * FROM Car ORDER BY HP DESC LIMIT 5 OFFSET 5;
CARIDPLATENUMBERBRANDCOLORHPOWNER
F78HD-MT 2510?green260?
F77HD-MT 2509?red184?
F14HD-MM 1977Mercedeswhite184H03
F05HD-MM 3206Mercedesblack184H03
F07HD-IK 1002VWblack184H07

Note

The LIMIT and OFFSET clauses are not part of the SELECT clause, but are the last clauses of a SELECT statement.