SELECT
SELECT — retrieve rows from a table or view
Syntax
SELECT [ optimizer_hint ]
[ ALL | DISTINCT ]
{ select_item [ [AS] output_name ] } [, ...]
FROM from_item
[ WHERE condition ]
[ GROUP BY [ DISTINCT | ALL] { expression | grouping_sets_specification } [,...] [ HAVING condition [, ...] ] ]
[ INTERSECT | EXCEPT | UNION [ ALL | DISTINCT ] select ]
[ ORDER BY { order_list [ COLLATE collation_name ] [ ASC | DESC] } [, ...] ]
[ LIMIT { count [ OFFSET start ] | start [ , count ] }
[ OFFSET start [ ROW | ROWS ] [ FETCH {FIRST | NEXT}
count [ROW | ROWS] [ONLY] ] ]
[ FETCH {FIRST | NEXT } count [ROW | ROWS] [ONLY] ]
[ FOR UPDATE [ NOWAIT | SKIP LOCKED | WAIT <lock_timeout_in_sec> ] ]
Where select_item can be any one of the following:
* | table.* | view.* | alias.*
[[schema.]table.]column_name | [[schema.]view.]column_name | [alias.]column_name
expr
query
scalar_function
NEXT VALUE FOR seq_name
Where from_item can be any one of the following:
[schema.]object_name [ [AS] alias ] [, ...]
( select ) [ [AS] alias ] [, ...]
from_item { join_type from_item
{ ON join_condition [...] | USING (column_name [, ...]) } }
scalar_function | table_function | [schema.]object_name table_sample
Where grouping_sets_specification can be any one of the following:
ROLLUP ((expression [,...]) [,...])
CUBE ((expression [,...]) [,...])
GROUPING SETS ( {(expression [,...] | grouping_sets_specificiation}[,...])
()
Description
Use a SELECT statement or subquery to retrieve data from one or more tables or views.
Use of SELECT for accessing sequences is discussed separately below.
An abstract version of the processing steps for a SELECT statement is as follows:
-
The actual output rows are computed using the
SELECToutput expressions for each selected row (seeSELECTlist below). -
SELECT DISTINCTeliminates duplicate rows from the result set. -
SELECT ALL(the default) returns all candidate rows, including duplicates (seeALL|DISTINCTunderSELECTlist below). -
All elements in the
FROMlist are computed. (Each element in theFROMlist is a real, derived, or virtual table (as inDUAL), or a view.) If more than one element is specified in theFROMlist, separated by commas, they are joined together (seeFROMlist below). -
If the
WHEREclause is specified, all rows that do not satisfy the condition are eliminated from the output (seeWHEREbelow). -
If the
GROUP BYclause is specified, the output is aggregated into groups of rows that match on one or more values. If theHAVINGclause is also present, NuoDB eliminates groups that do not satisfy the given condition (seeGROUP BYbelow). -
The
INTERSECToperator combines the output of multipleSELECTstatements to form a single result set. TheINTERSECToperator returns all rows that are common in both of the result sets. Duplicate rows are eliminated.The
EXCEPToperator combines the output of multipleSELECTstatements to form a single result set. TheEXCEPToperator returns all rows that are present in the first query and not in the second query. Duplicate rows are eliminated.The
UNIONoperator combines the output of multipleSELECTstatements to form a single result set. TheUNIONoperator returns all rows that are in one or both of the result sets. Duplicate rows are eliminated unlessUNION ALLis specified. Notice thatUNION DISTINCTis the default here, as duplicate rows are eliminated, even thoughALLis the default for theSELECTitself (seeUNIONbelow). NuoDB uses a common type algorithm (Data Type Conversion) to decide the type, precision and scale of each column in the result of a query with UNION branches and coerces the columns in each branch to the common type. The common type is computed from the top down through the branches and is not commutative. -
If the
ORDER BYclause is specified, the returned rows are sorted in the specified order. IfORDER BYis not given, the rows are returned in whatever order the system finds fastest to produce (seeORDER BYbelow). Use the keywordCOLLATEto change the character classification behavior of the sort order. -
If the
LIMIT,OFFSETorFETCHclause is specified, theSELECTstatement returns a subset of the result set (seeLIMIT,FETCH,OFFSETbelow). -
The
FOR UPDATEclause controls whether the transaction for the current session places a lock on the retrieved records (seeFOR UPDATEbelow).
Results of queries to the Transaction Engine (TE) will be buffered back to the client in rows that fit into less than 100 KB. Once the client iterates through a set of fetched results, it will go back to the TE to get more results.
You must have SELECT privilege on all tables and/or views to access them in a SELECT command. The use of FOR UPDATE requires UPDATE privilege on the table being updated. Views cannot be updated.
|
| The use of a column alias cannot be used in the WHERE, GROUP BY, or HAVING clause. For example, "SELECT field as F FROM table WHERE F > 0" is not supported. Allowing such a condition can result in ambiguous name resolution and therefore is not allowed. |
Parameters
SELECTlist-
The
SELECTlist (between the keywordsSELECTandFROM) lets you specify the columns you want to retrieve from the database. This list forms the output rows of theSELECTstatement. ASELECTstatement that selects rows from two or more tables and/or views is a join.optimizer_hintAn optimizer hint is a mechanism for you to tell the optimizer how to execute the query. For more information see Optimizer Hints below.
ALL | DISTINCTIf
SELECT DISTINCTis specified, all duplicate rows are removed from the result set (one row is kept from each group of duplicates).SELECT ALLspecifies the opposite: all rows are kept; this is the default (see Example 1).* | table.* | view.* | alias.*An asterisk (
*) can be written in the output list as a shorthand for all columns of the selected rows. Also, you can writetable.*orview.*as a shorthand for the columns coming from just that table or view. In these cases it is not possible to specify new names withAS; the output column names will be the same as the table or view column names. NuoDB returns a set of columns in the order in which the columns were specified when the table or view was created.[[schema.]table.]column_name | [[schema.]view.]column_name | [alias.]column_nameSpecifies one or more columns that exist in tables and or views in the
FROMclause. Acolumn_namein this list can be optionally qualified with a table or view name and a schema name.ROWNUM()This is a NuoDB SQL system function that will return a unique identifier for each row relative to its position in the result set. In other words, it is related to the row’s position in the result set after all joins and predicates are evaluated. Prior to any sorting or
GROUP BYbeing applied to the result set, this function will always return a sequential unique identifier for each row. Using anORDER BYorGROUP BYclause changes this sequential ordering. See Example 17. For more details and limitations, seeROWNUM()function.exprSpecify an expression representing the information you want to select. This can be in the form of a function or mathematical operator (see
CREATE FUNCTIONand SQL Functions and Operations) or an expression. A column name in this list can be optionally qualified with a table or view name and a schema name (see Example 2). Additional examples of using user defined functions as an item in a select list can be found with theCREATE FUNCTIONdocumentation.queryThis is a valid SELECT statement, in parentheses, called a scalar subquery. This SELECT statement MUST retrieve exactly one row per each row selected in the surrounding SELECT statement. It can only select one column. If during execution, the subquery returns no rows, there is no error; the scalar result is taken to be NULL. The subquery can refer to variables from the surrounding query, which act as constants during any one evaluation of the scalar subquery (see Example 3).
scalar_functionThis is a function that returns a single column row. The data type of the column is defined by the
RETURNclause of the function definition. This can be defined as any type of function, including:-
A User Defined function (UDF) (see CREATE FUNCTION)
-
A NuoDB defined pseudo function (see SQL System Information Functions)
-
A NuoDB SQL function (see SQL Functions and Operations)
ASoutput_nameJust as in a table, every output column of a
SELECThas a name. In a simpleSELECTthis name is just used to label the column for display (see Example 2), but when theSELECTis a subquery of a larger query, the name is seen by the larger query as the column name of the virtual table produced by the subquery (see Example 3) .To specify the name to use for an output column, write
ASoutput_nameafter the column’s expression. (You can omitAS, but only if the desired output name does not match any NuoDB keyword. For protection against possible future keyword additions it is recommended that you always either writeASor double-quote theoutput_name.)If you do not specify a column name, a name is chosen automatically. If the column’s expression is a simple column reference then the chosen name is the same as the column’s name. In more complex cases, the function name may be used (see SQL Functions and Operations), or NuoDB may leave the column heading blank, as in the case with a subquery (see Example 3).
An
output_namecan be used to refer to the column’s value in theWHERE,ORDER BY,GROUP BY, andHAVINGclauses;Restrictions on the
SELECTlist:If you specify a
GROUP BYclause in aSELECTstatement, then theSELECTlist can only contain the following types of expressions: -
Constants
-
Aggregate functions
-
Expressions identical to those in the
GROUP BYclause. If theGROUP BYclause is in a subquery, then theGROUP BYcolumns of the subquery must match theSELECTlist of the outer query. Any columns in theSELECTlist of the subquery that are not needed by theGROUP BYoperation are ignored without error. -
Expressions involving the preceding expressions that evaluate to the same value of all rows in a group.
If two or more tables have some column names in common, and if you are specifying a join in the
FROMclause, then you must qualify column names with the names or aliases of the tables and/or views.
-
FROMlist-
The
FROMclause specifies one or more data sources for theSELECT. If theSELECTstatement contains no restrictions in itsON,USING, orWHEREclause, the result is the full cross product (Cartesian join) of all the sources. Typically, qualification conditions are added to restrict the returned rows to a small subset of the Cartesian join.[schema.]object_nameThe name (optionally schema-qualified) of an existing table or view.
( select)A sub-
SELECTcan appear in theFROMclause. This acts as though its output were created as a temporary table for the duration of this singleSELECTstatement and is called a derived table. Note that the sub-SELECTmust be surrounded by parentheses, and analiasmust be provided for it (see Example 4).AS aliasA substitute name for the
FROMitem containing the alias. An alias is used for brevity or to eliminate ambiguity for multiple tables and/or views having the same column names and for self-joins (where the same table is scanned multiple times). All sub-SELECTstatements (derived tables) in theFROMclause must be given analias.join_typeFor the
INNERandOUTERjoin types, a join condition (ONorUSING) must be specified.A
JOINclause combines twoFROMitems.-
[INNER ] JOININNER JOINreturns combined records from eachFROMitem, matched by the condition(s) in theONclause. Thisjoin_typeis a notational convenience, since they do nothing you could not do with plainFROMandWHERE(see Example 5). -
LEFT [OUTER] JOINLEFT OUTER JOINreturns combined records from eachFROMitem, matched by the condition(s) in theONclause, plus one copy of each row in the left-handFROMitem for which there was no right-hand row that passed theJOINcondition. This left-hand row is extended to the full width of the joined result set by inserting null values for the right-hand columns (see Example 6). -
RIGHT [OUTER] JOINRIGHT OUTER JOINreturns combined records from each table specified in the FROM clause, matched by the condition(s) in theONclause. Additionally, it includes a copy of all the rows from the right-handFROMitem for which there was no left-hand row that passed theJOINcondition. This right-hand row is extended to the full width of the joined result set by inserting null values for the left-hand columns. -
FULL OUTER JOINFULL OUTER JOINreturns combined records from each FROM item, including all matched rows based on the condition(s) in the ON clause, and unmatched rows from both sides, with NULL values for missing columns.ON join_conditionAn expression resulting in a value of type Boolean (similar to a
WHEREclause) that specifies which rows in a join are considered to match. Thejoin_conditionin theONclause should include only Boolean values that describe the relationship between theFROMitems being joined.USING ( column_name [,column_name] )USINGis a shorthand notation and accepts one or more column names, separated by a comma, which the joined tables must have in common, and forms a join condition specifying equality of each of these pairs of columns.The column list of the result set for a
JOINwithUSINGis different than the column list of the result set for all otherJOINoperations (see Example 14). ThisUSINGresult set column list order is based on the following rule:-
Coalesced columns of the two joined tables, used in the
USINGclause, in the order in which they appear in the first table. -
Columns unique to the first table, in the order in which they appear in that table.
-
Columns unique to the second table, in the order in which they appear in that table.
-
scalar_function|table_function|[schema.]object_name table_sample-
scalar_function: a function that returns a single column row. For more information, seeCREATE FUNCTION. -
table_function: a function that returns a result set with multiple columns. For more information, see SQL Table Functions. -
table_sample: a function that returns a random subset of rows from the specified table. Syntax fortable_sampleis:TABLESAMPLE [ SYSTEM | BERNOULLI ] (<percentage>) [ REPEATABLE (<seed_value>)]The number of rows returned is specified using
percentage.percentageis a float value ranging from0to100.SYSTEMis the default sampling method. This method randomly selects entire pages based on the percentage value specified. For example, if the percentage value specified is20, then each page has a 20% chance of being selected in the sample. TheSYSTEMsampling method is faster thanBERNOULLI.The
BERNOULLImethod checks each row individually and includes or excludes it based on the percentage value specified. This method returns an evenly distributed table sample.The
REPEATABLE (seed_value)option is used to reproduce the same result set as long as the table does not change between samples.seed_valueis an integer. Using the sameseed_valuewill return same set of sample rows.For example:
SELECT count(*) FROM sample_table;[COUNT] -------- 1000000SELECT count(*) FROM sample_table TABLESAMPLE (20);[COUNT] -------- 190464SELECT count(*) FROM sample_table TABLESAMPLE SYSTEM (20);[COUNT] -------- 210944SELECT count(*) FROM sample_table TABLESAMPLE BERNOULLI (20);[COUNT] -------- 200197SELECT count(*) FROM sample_table TABLESAMPLE BERNOULLI (20) REPEATABLE (123);[COUNT] -------- 199486
-
WHERE condition-
The optional
WHEREclause has several forms:expressionAn
expressionthat evaluates to a result of type Boolean using comparison operations (see SQL Functions and Operations). Any row that does not satisfy this condition is eliminated from the output. A row satisfies the condition if it returns true when the actual row values are substituted for any variable reference. This expression can also compare the returned value from a scalar function.{ EXISTS | NOT EXISTS } ( SELECT )A parenthesized subquery
SELECTstatement is evaluated to determine whether it returns any rows. If it returns at least one row, the result ofEXISTSis "true" and the result ofis "false". If the subqueryNOT EXISTSSELECTstatement returns zero rows, the result ofEXISTSis "false" and the result ofis "true".NOT EXISTSThe
SELECTstatement can refer to items in theFROMlist, regardless of whether they are also items in theSELECTlist (see Example 7).expression { IN | NOT IN } ( SELECT )The right-hand side is a parenthesized subquery
SELECTstatement, which must select exactly one column. The left-hand expression is evaluated and compared to each row of the subquery result. The result ofINis "true" if any equal subquery row is found. The result is "false" if no equal row is found (including the case where the subquery returns no rows).Note that if the left-hand expression yields
NULL, or if there are no equal right-hand values and at least one right-hand row yieldsNULL, the result of theINconstruct will beNULL, not false (see Example 8). GROUP BY expression-
The optional
GROUP BYcondenses into a single row all selected rows that share the same values for the grouped expressions. The expression can be a column name, or the alias, or ordinal number of an item in theSELECTlist.Aggregate functions, if any are used, are computed across all rows making up each group, producing a separate value for each group.
Without
GROUP BY, an aggregate produces a single value computed across all the rows returned in the result set. WhenGROUP BYis present, the items in theSELECTlist cannot refer to ungrouped columns, except within aggregate functions. Otherwise there would be more than one possible value to return for an ungrouped column (see Example 9). GROUP BY ROLLUP-
GROUP BY ROLLUPis used to compute grand-totals of aggregates grouped by successively smaller prefixes of grouping keys within a single query.The order of the columns in the clause will affect the grouping. For example:
SELECT country, state, city FROM employee;COUNTRY STATE CITY -------- ------- ------ germany bavaria munichSELECT country, state, city, Count(*) FROM employee GROUP BY rollup ( ( country ), ( state ), ( city ) );COUNTRY STATE CITY [COUNT] -------- ------- ------ -------- germany bavaria munich 1 germany bavaria <null> 1 germany <null> <null> 1 <null> <null> <null> 1 GROUP BY CUBE-
GROUP BY CUBEis used to compute aggregates grouped by all possible combinations of the specified columns within a single query.For example:
SELECT country, state, city, Count(*) FROM employee GROUP BY cube ( ( country ), ( state ), ( city ) );COUNTRY STATE CITY [COUNT] -------- ------- ------ -------- germany bavaria munich 1 <null> bavaria munich 1 germany <null> munich 1 <null> <null> munich 1 germany bavaria <null> 1 <null> bavaria <null> 1 germany <null> <null> 1 <null> <null> <null> 1 GROUP BY GROUPING SETS-
GROUP BY GROUPING SETSis used to compute aggregates grouped arbitrary sets of columns within a single query.For example:
SELECT country, state, city FROM employee;COUNTRY STATE CITY -------- ------- ------ germany berlin berlin germany bavaria munichSELECT country, state, city, Count(*) FROM employee GROUP BY grouping sets ( ( country, state ), ( city ), ( state ), ( ) );COUNTRY STATE CITY [COUNT] -------- ------- ------ -------- <null> <null> berlin 1 germany berlin <null> 1 <null> berlin <null> 1 <null> <null> <null> 2 <null> <null> munich 1 germany bavaria <null> 1 <null> bavaria <null> 1 HAVING condition-
The optional
HAVINGeliminates grouped rows that do not satisfy the condition.HAVINGis different fromWHEREin thatWHEREfilters individual rows before the application ofGROUP BY, whileHAVINGfilters grouped rows created byGROUP BY.GROUP BYis required for usingHAVING. Unless the reference appears within an aggregate function, each item referenced inconditionmust unambiguously reference a grouping column (see Example 9). INTERSECT | EXCEPT | UNION [ALL|DISTINCT] select-
The
selectitem is any validSELECTstatement.The
INTERSECT,EXCEPT, orUNIONclause is used to combine the result set returned by multipleSELECTstatements into one result set. TheSELECTlist for all SELECT statements in aINTERSECT,EXCEPT, orUNIONstatement must contain the same number of columns, and the corresponding columns must be of compatible data types.The
INTERSECToperator returns all rows that are common in both of the result sets.The
EXCEPToperator returns all rows that are present in the first query and not in the second query.Duplicate rows are eliminated when using the
INTERSECTandEXCEPToperatorsIf a row is returned in the result set of at least one of the
SELECTstatements in theUNION, then the row is returned in the combined result set.ORDER BY,LIMIT,OFFSETandFETCHclauses cannot be applied separately to eachSELECTstatement in aUNIONstatement (see Note below for work-around). These clauses can only apply to the combined result set of theUNIONand must be specified at the end of theUNIONstatement, after all of theSELECTstatements for theUNION(see Example 11).It is possible to sort the result set of each individual SELECTstatement of aUNIONseparately. This is done by replacing eachSELECTstatement of theUNIONwith a select from a derived table which is created using eachSELECTstatement (see Example 11).FOR UPDATEcannot be specified.By default, the combined result set of a
UNIONwill not contain duplicate rows. In other words, if a row is returned in the result set of one or more of theSELECTstatement in theUNION, that row will only appear once in the combined result set. This can be explicitly written asUNION DISTINCT. UseUNION ALLto include duplicate rows in the combined result set (see Example 10). ORDER BY order_list-
The optional
ORDER BYcauses the rows returned in the result set to be sorted according to the specified expressions in theORDER BYorder_list. If two rows are equal according to the left most expression, they are compared according to the next expression and so on. If they are equal according to all specified expressions, they are returned in an implementation-dependent order.Normally, it is possible to use items in the
order_listthat do not appear in theSELECTlist. The exception to this is aSELECTstatement using aUNIONfor the combined result set. In this case, only items being returned in theSELECTlist can be referred to in theORDER BYorder_list. These can be referred to by name or by the position number that the item is returned in the result set.If an output name is assigned to an item in the
SELECTlist, this actual item name needs to be referred to in theORDER BYorder list, and not the output name. This is true when using any type of expression as an item in the select list, including user defined functions. The exception to this is in the use of output names used in aUNION. Since that becomes the name of the item in the combined result set, that output name needs to be used to refer to that column in theORDER BYorder_list(see Example 11).Use of the
RAND()function in theORDER BYclause will return the result set in a random order.SELECTstatements usingUNIONalso allowORDER BY RAND().COLLATEcollation_typeA collation type can be defined to change the character classification behavior of the sort order of a result set (see Example 12). Supported collation types include:
case_insensitiveand"8859-1U". Both collation types are synonyms for each other, soCOLLATE case_insensitivewill produce the same result asCOLLATE "8859-1U".ASC | DESCOne may add the keyword
ASC(ascending) orDESC(descending) after any item in theorder_listin theORDER BYclause. If not specified,ASCis the default. LIMIT,FETCH,OFFSET-
countSpecifies the maximum number of rows to return for the result set. If zero, the result set returns zero number of rows.
startSpecifies the number of rows to skip before starting to return rows for the result set. The default value is
0. ANULLvalue is converted to0.Both
countandstartcan be one of the following: a non-negative integer value, an expression that can be cast to a non-negative integer value, a non-negative decimal value that is cast to an integer value by rounding. Bothcountandstartcannot be the results of a scalar subquery.The
FETCHparameter must include one of the keywordsFIRSTorNEXT. The returned result set is the same regardless of which keyword is used.LIMITandFETCHare different parameters that achieve the same result. When eitherLIMITorFETCHis used withOFFSET, the number of rows specified as theOFFSETis skipped before starting the count for the number of rows to be returned. Thecountandstartexpressions cannot beNULL. TheOFFSETclause must come before theFETCHclause if both are present. An offset value may be specified toLIMITwithout theOFFSETkeyword using the syntaxstart,offset.Specifically,
LIMITsupports the following three syntaxes:-
LIMITcount -
LIMITstart, count -
LIMITcountOFFSETstartSee Example 13 for examples of using
LIMIT,FETCHandOFFSET.
When using
LIMITorFETCH, it is a good idea to use anORDER BYclause that constrains the result rows into a unique order. Otherwise, you will get an unpredictable subset of the query’s rows. For example, you might be asking for the tenth through twentieth rows, but tenth through twentieth in what ordering? You don’t know what ordering unless you specifyORDER BY. This is because NuoDB performs theORDER BYbefore it does theLIMITorFETCH.It is not good practice to use an ORDER BYin aVIEWdefinition or a derived table. To improve performance, the NuoDB optimizer will ignore ordering of the result set returned by theVIEWor derived table, unless aLIMITorOFFSETis also supplied, along with theORDER BY. Let’s say you have defined aVIEWwith anORDER BYand now you want toSELECTfrom theVIEWand order the results differently. The optimizer would require an execution plan that performs two sorts. In NuoDB, this execution plan requires only one sort. -
FOR UPDATE-
The
FOR UPDATEclause will lock those records in the associated tables that satisfy the query and have been fetched to the client. Results of queries to the TE are buffered back to the client in rows that fit into less than 100 KB. Only rows in results that have been fetched back to the client already will be locked. TheFOR UPDATEclause requires that a session level transaction be in effect. SeeSTART TRANSACTIONfor how to create a session level transaction. See Supported Transaction Isolation Levels, for an illustration of howSELECT…FOR UPDATEbehaves across the different transaction isolation levels that NuoDB supports. When theFOR UPDATEquery contains a user defined function, no records in tables accessed by the function are locked.If the
NOWAIToption is specified, and the record that is going to be locked is already locked by another transaction, an exception is thrown immediately instead of waiting for the other transaction to release the lock.If the
SKIP LOCKEDoption is specified, the rows locked by another transaction are skipped.If the
WAIToption is specified and the record that is going to be locked is already locked by another transaction, the current transaction will wait for the specified time. If the transaction cannot acquire a lock within the specified time, an exception is thrown.When using FOR UPDATEwith theREAD COMMITTEDisolation level, the query will be internally run twice. The first run will attempt to lock the affected records, then the processing will restart to produce the output from the query.
Accessing Sequences
To access the next value from a sequence use NEXT VALUE FOR sequence_name.
This can be part of a longer SELECT statement or to just fetch the next value use:
SELECT NEXT VALUE FOR sequence_name FROM DUAL
The value is always a 64-bit integer, but you can cast it like this:
SELECT cast(NEXT VALUE FOR sequence_name AS SMALLINT) ...
Sequences in NuoDB may be shared by multiple TEs, so when a TE accesses a sequence it gets its own set of values.
The default size of that set (the QUANTUM SIZE) is 100.
So if a client connects to the first TE to use the sequence, the result of SELECT NEXT VALUE will be 1.
However, if the client connects to the second TE to use the sequence, then SELECT NEXT VALUE will return 101.
As a result the values from SELECT NEXT VALUE are guaranteed to be unique but there may be gaps in the values returned and (if a client is using multiple threads against multiple TEs) the values are not necessarily in an increasing order.
For example, successive calls to SELECT NEXT VALUE might return 101, 1, 2, 102 …
See also CREATE SEQUENCE.
Optimizer Hints
Optimizer hints are a means to indicate how the query engine should evaluate specific operations of a query plan statement.
For example, you may know, based on the data in a given column, and the predicate(s) applied to this column, that scanning a certain index may be faster than another which was chosen automatically by the optimizer.
This may be the case when database statistics are too old or missing.
Optimizer hints are embedded in the SQL query, right after the SELECT keyword.
The format of optimizer hints is as follows:
/*+ hint[,hint]… */
Where the following values (case-insensitive) are allowed to substitute for hint:
ORDERED
USE_INDEX ( [schema.]table [ , index_list ] )
SKIP_INDEX ( [schema.]table [ , index_list ] )
USE_ORDERING ( [schema.]table [ , index_list ] )
HASHMATERIALIZE [ ( [schema.]table ) ]
NO_HASHMATERIALIZE [ ( [schema.]table ) ]
NO_MERGE
REOPTIMIZE { ALWAYS | NEVER }
table is the name of a table or its alias, as specified in the AS alias clause of the SELECT statement.
The table name may optionally be schema qualified.
If a table has an alias then all index hints on that table must reference the alias.
index_list is a list of one or more index specifications separated by commas, where each index specification has the format:
[ ID_ORDERED ] index_name
[ KEY_ORDERED ] index_name
ID_ORDERED and KEY_ORDERED designate the scan type for the index.
ID_ORDERED refers to an index scan operation that is reading data in ROWID order.
KEY_ORDERED refers to an index scan operation that is reading data in index key order.
If you specify conflicting hints (for example, /*+ USE_INDEX(foo, foo_a), SKIP_INDEX(foo, foo_a) */), where foo is a table and foo_a is an index on a column in table foo, an error will be thrown.
|
The quoted table or index names in index hints must be specified in uppercase.
For example, |
ORDERED Hint
The ORDERED hint tells the optimizer to join tables in the order that they are specified in the FROM clause.
Example:
SELECT /*+ ORDERED */ COUNT(*)
FROM t1, t2, t4, t3 WHERE t1.col = t2.col AND t1.col = t3.col AND t1.col = t4.col;
USE_INDEX Hint
USE_INDEX ( [schema.]table [ , index_list ] )
Note: You can use [schema.]table or you may need to use table alias. This is needed if you do a join between the same table more than once.
The USE_INDEX hint tells the optimizer to use an index (or a set of indexes) for a table.
-
If the hint specifies a single index, then the optimizer uses that index. The optimizer does not consider any other index or indexes for the table.
-
If the hint specifies multiple indexes, then the optimizer chooses an optimal index plan based on the specified indexes. The optimizer does not guarantee that all specified indexes are going to be used in the plan.
-
If the hint specifies no indexes, then the optimizer chooses an optimal index plan based on all available indexes over the table. The optimizer does not consider a full scan over the table.
-
If the hint specifies a scan type (
ID_ORDEREDorKEY_ORDERED) for an index, then the optimizer considers that index for that type of scan only.ID_ORDEREDrefers to an index scan that is reading data inROWIDorder.KEY_ORDEREDrefers to a query that is reading data in index key order.
For example, if the hint specifies ‘KEY_ORDERED foo_a’, then the optimizer will use thefoo_aindex when it is doing a key ordered scan forORDER BYorGROUP BYoptimization. -
If the hint does not specify a scan type (
ID_ORDEREDorKEY_ORDERED) for an index, then the optimizer considers that index for both key ordered and id ordered query plans,.
Example:/*+ USE_INDEX(foo, foo_a) */ -
If the
index_listspecifies bothID_ORDEREDandKEY_ORDEREDspecifications for an index, then the optimizer considers that index for both key ordered and id ordered query plans.
Examples:/*+ USE_INDEX(foo, ID_ORDERED foo_a, KEY_ORDERED foo_a) */ /*+ USE_INDEX(foo, ID_ORDERED foo_a), USE_INDEX(foo, KEY_ORDERED foo_a) */
In the examples above, foo is a table and foo_a is an index on a column in table foo.
See Example 15 below.
SKIP_INDEX Hint
SKIP_INDEX ( [schema.]table [ , index_list ] )
Note: You can use [schema.]table or you may need to use table alias. This is needed if you do a join between the same table more than once.
The SKIP_INDEX hint tells the optimizer to not use an index (or a set of indexes) for a table.
-
If the hint specifies a single index, then the optimizer does not consider that index. The optimizer considers the other indexes on the table.
-
If the hint specifies multiple indexes, then the optimizer does not consider any of the specified indexes. The optimizer still considers other indexes that are not specified.
-
If the hint specifies no indexes, the optimizer does not consider any of the indexes on the table. The optimizer will choose a full scan for the table.
-
If the hint specifies a scan type (
KEY_ORDEREDorID_ORDERED) for an index, then the optimizer does not consider that index for that type of scan only.ID_ORDEREDrefers to an index scan that is reading dataROWIDorder.KEY_ORDEREDrefers to an index scan that is reading data in index key order.
For example, if the hint specifies ‘ID_ORDERED foo_a’, the optimizer still considersfoo_awhile choosing a plan in the context ofORDER BYorGROUP BYoptimization. -
If the hint does not specify a scan type for an index, then the optimizer does not consider that index for both id ordered and key ordered query plans.
Example:/*+ SKIP_INDEX(foo, foo_a) */ -
If the hint specifies both
KEY_ORDEREDandID_ORDEREDfor an index, then the optimizer does not consider that index for both id ordered and key ordered query plans.
Examples:/*+ SKIP_INDEX(foo, KEY_ORDERED foo_a, ID_ORDERED foo_a) */ /*+ SKIP_INDEX(foo, KEY_ORDERED foo_a), SKIP_INDEX(foo, ID_ORDERED foo_a) */
In the examples above, foo is a table and foo_a is an index on column a in table foo.
See Example 16 below.
HASHMATERIALIZE and NO_HASHMATERIALIZE Hints
The HASHMATERIALIZE hint is useful for equi-joins when at least one of the tables doesn’t have a suitable index on the join column(s).
This could be either a base or an unmerged derived table.
The hint instructs the query optimizer to materialize the table and create a hash-index on the join column(s).
The resulting join operation is called Hash-join.
Correspondingly, the NO_HASHMATERIALIZE hint disables the hash-join strategy for the table it references.
Example 1
Base tables are referenced as the only argument of the hint inside the SELECT clause of the query.
explain select /*+hashmaterialize(t1)*/ * from t1, t2 where t1.f1 = t2.f2;
Project F1, F2, F1, F2
Nested Loop Join (cost: 4903.0, est. rows: 1700)
Table scan T2 (cost: 1201.0, est. rows: 100)
Hash lookup on (T1.F1 = T2.F2) (cost: 3602.0, est. rows: 17)
Materialize stream
Table scan T1 (cost: 3601.0, est. rows: 300)
Example 2
The hint can be used inside a derived table without an argument. In this case it refers to the derived table itself, so that it is materialized in the parent query.
explain select * from (select /*+hashmaterialize*/ f1, f2 from t1 group by f1, f2) t1, t2 where t1.f1 = t2.f2;
Project F1, F2, F1, F2
Nested Loop Join (cost: 4903.0, est. rows: 30000)
Table scan T2 (cost: 1201.0, est. rows: 100)
Hash lookup on (T1.F1 = T2.F2) (cost: 3602.0, est. rows: 300)
Materialize stream
StreamedGrouping keys { T1.F1, T1.F2 } (cost: 3601.0, est. rows: 300)
Sort T1.F1 ASC T1.F2 ASC
Table scan T1 (cost: 3601.0, est. rows: 300)
NO_MERGE Hint
The NO_MERGE hint prevents the optimizer from merging derived queries or views in an OUTER JOIN.
REOPTIMIZE Hint
REOPTIMIZE { ALWAYS | NEVER }
The REOPTIMIZE hint can be used to force the optimizer to perform a full reoptimization on each execution of a query.
A full reoptimization may help to improve the query plan generated by the optimizer in cases where user parameters or variables are used in the query and when the value of the parameters or variables can significantly influence the chosen query plan.
|
The optimizer will automatically reoptimize, without using a hint, when all of the following conditions are true:
This automatic reoptimization can be disabled by using the |
Example
create table t1 (f1 int primary key, f2 string);
insert into t1 values (1, 'one'), (2, 'two'), (3, 'three'), (4, 'four'), (5, 'five');
explain (analyze on) select /*+ REOPTIMIZE ALWAYS */ * from t1 where f1 < ?;
Enter value: 6
Project T1.F1, T1.F2 (actual rows: 5, time: 37us, batches: 2)
Filter (CAST(T1.F1 AS numeric(38,*)) < 6) (actual rows: 5, time: 35us, batches: 2)
Table scan T1 (cost: 71.0, est. rows: 5, actual rows: 5 in 1 record, 1 data atoms (imported 0 (0KB)), time: 26us, batches: 1)
explain (analyze on) select /*+ REOPTIMIZE NEVER */ * from t1 where f1 < ?;
Enter value: 6
Project T1.F1, T1.F2 (actual rows: 5, time: 46us, batches: 2)
Record fetch T1 (cost: 33.4, est. rows: 2, actual rows: 5 in 1 record, 1 data atoms (imported 0 (0KB)), time: 46us, batches: 2)
Bitmap filter
Bitmap scan T1..PRIMARY_KEY (F1[-inf:<?:1]) (cost: 4.4, est. keys: 2, actual keys: 5 in 1 record, 1 index atoms (imported 0 (0KB)), time: 29us)
Examples for SELECT
- Example 1: Use of
SELECT ALLcompared withSELECT DISTINCT -
SELECT ALL playerid,year,stint FROM scoring WHERE year = 2009 AND playerid LIKE 'boy%' ORDER BY playerid; PLAYERID YEAR STINT --------- ----- ------ boychjo01 2009 1 boychza01 2009 1 boyddu01 2009 1 boyddu01 2009 2 boyesbr01 2009 1 boylebr01 2009 1 boyleda01 2009 1 boyntni01 2009 1 boyntni01 2009 2 SELECT DISTINCT playerid,year FROM scoring WHERE year = 2009 AND playerid LIKE 'boy%' ORDER BY playerid; PLAYERID YEAR --------- ----- boychjo01 2009 boychza01 2009 boyddu01 2009 boyesbr01 2009 boylebr01 2009 boyleda01 2009 boyntni01 2009 - Example 2:
SELECTusing functions, operators and expressions and the use of output display names -
SELECT cast(birthmon||'/'||birthday||'/'||birthyear as date) AS BIRTH_DATE, CASE birthcountry WHEN 'USA' THEN 'United States' ELSE 'Other' END AS BIRTH_COUNTRY, LASTNHL-FIRSTNHL AS YEARS, UPPER(FIRSTNAME), UPPER(LASTNAME), WEIGHT FROM players WHERE birthday > 0 AND weight > 250; BIRTH_DATE BIRTH_COUNTRY YEARS FIRSTNAME LASTNAME WEIGHT ----------- -------------- ------ ---------- --------- ------- 1983-04-04 Other 4 EVGENY ARTYUKHIN 254 1982-06-23 Other 5 DEREK BOOGAARD 254 1985-03-27 United States 6 DUSTIN BYFUGLIEN 265 1977-03-18 Other 14 ZDENO CHARA 255 1967-10-16 Other 1 GERRY FLEMING 253 1978-12-28 Other 1 KYLE FREADRICH 260 1979-01-01 Other 6 RAITIS IVANANS 263 1981-05-21 Other 3 KRISTIAN KUDROC 255 1980-08-08 Other 3 STEVE MACINTYRE 265 1973-08-21 Other 7 STEVE MCKENNA 252 1982-09-26 Other 3 JOHN SCOTT 258 - Example 3:
SELECTexpression using a scalar subquery as an expression in the select list and using output display names as compared with no output display name -
SELECT s.PLAYERID, s.year, s.stint, s.teamid, (SELECT name FROM teams t WHERE t.teamid = s.teamid and t.year = s.year) FROM scoring s WHERE s.YEAR = 2011 AND s.teamid like 'B%'; PLAYERID YEAR STINT TEAMID --------- ----- ------ ------- -------------- adamlu01 2011 1 BUF Buffalo Sabres bartkma01 2011 1 BOS Boston Bruins bergepa01 2011 1 BOS Boston Bruins boychjo01 2011 1 BOS Boston Bruins boyesbr01 2011 1 BUF Buffalo Sabres brenntj01 2011 1 BUF Buffalo Sabres ... SELECT s.PLAYERID, s.year, s.stint, s.teamid, (SELECT name FROM teams t WHERE t.teamid = s.teamid and t.year = s.year) AS TEAM FROM scoring s WHERE s.YEAR = 2011 AND s.teamid like 'B%'; PLAYERID YEAR STINT TEAMID TEAM --------- ----- ------ ------- -------------- adamlu01 2011 1 BUF Buffalo Sabres bartkma01 2011 1 BOS Boston Bruins bergepa01 2011 1 BOS Boston Bruins boychjo01 2011 1 BOS Boston Bruins ... - Example 4:
SELECTstatement using a subquery in theFROMlist -
SELECT a.team_year, a.team_teamid, a.team_conf, a.team_div FROM (SELECT t.year AS team_year,t.teamid AS team_teamid, t.rank AS team_rank , t.conferenceid AS team_conf, t.divisionid AS team_div FROM teams t) a WHERE a.team_rank = 1 AND a.team_year = 2011; TEAM_YEAR TEAM_TEAMID TEAM_CONF TEAM_DIV ---------- ------------ ---------- --------- 2011 BOS EC NE 2011 FLO EC SE 2011 NYR EC AT 2011 PHO WC PC 2011 STL WC CE 2011 VAN WC NW - Example 5:
SELECTstatement usingINNER JOINand aWHEREclause to filter the combined result set -
SELECT s.playerid, s.teamid, t.name, t.conferenceid, t.divisionid, t.rank FROM scoring s INNER JOIN teams t ON s.year = t.year AND s.teamid = t.teamid and t.rank =1 WHERE s.position = 'G' AND t.year = 2011; PLAYERID TEAMID NAME CONFERENCEID DIVISIONID RANK --------- ------- ----------------- ------------- ----------- ----- bironma01 NYR New York Rangers EC AT 1 clemmsc01 FLO Florida Panthers EC SE 1 elliobr01 STL St. Louis Blues WC CE 1 fostebr01 FLO Florida Panthers EC SE 1 halakja01 STL St. Louis Blues WC CE 1 ... - Example 6:
SELECTstatement usingLEFT OUTER JOINand aWHEREclause to filter and order the combined result set -
SELECT p.firstname,p.lastname,p.firstnhl,p.lastnhl,s.teamid,s.stint,gamesplayed FROM players p LEFT OUTER JOIN scoring s ON p.playerid = s.playerid AND p.firstnhl = s.year AND s.position = 'G' WHERE p.firstnhl = 2011 AND s.gamesplayed IS NOT NULL ORDER BY LASTNAME,FIRSTNAME,TEAMID; FIRSTNAME LASTNAME FIRSTNHL LASTNHL TEAMID STINT GAMESPLAYED ---------- --------- --------- -------- ------- ------ ------------ Brian Foster 2011 2011 FLO 1 1 Matt Hackett 2011 2011 MIN 1 12 Shawn Hunwick 2011 2011 CBS 1 1 Leland Irving 2011 2011 CAL 1 7 Mike Murphy 2011 2011 CAR 1 2 Anders Nilsson 2011 2011 NYI 1 4 Jussi Rynnas 2011 2011 TOR 1 2 Ben Scrivens 2011 2011 TOR 1 12 Iiro Tarkki 2011 2011 AND 1 1 Brad Thiessen 2011 2011 PIT 1 5 Allen York 2011 2011 CBS 1 11 - Example 7:
SELECTstatement usingEXISTS (SELECT…)to filter result set based on a subquery -
SELECT p.playerid, p.firstname, p.lastname FROM players p WHERE EXISTS (SELECT 'x' FROM scoring s WHERE s.playerid = p.playerid AND s.position = 'G' AND s.year = 2011); PLAYERID FIRSTNAME LASTNAME --------- -------------- ------------------ andercr01 Craig Anderson auldal01 Alex Auld bachmri01 Richard Bachman backsni01 Niklas Backstrom bernijo01 Jonathan Bernier bironma01 Martin Biron bishobe01 Ben Bishop bobrose01 Sergei Bobrovsky ... - Example 8:
SELECTstatement usingINto filter result set based on a subquery that returns a single column -
SELECT p.playerid, p.firstname, p.lastname FROM players p WHERE p.playerid IN (SELECT s.playerid FROM scoring s WHERE s.position = 'G' AND s.year = 2011); PLAYERID FIRSTNAME LASTNAME --------- -------------- ------------------ andercr01 Craig Anderson auldal01 Alex Auld bachmri01 Richard Bachman backsni01 Niklas Backstrom bernijo01 Jonathan Bernier bironma01 Martin Biron bishobe01 Ben Bishop bobrose01 Sergei Bobrovsky ... - Example 9:
SELECTstatement using aGROUP BYand an optionalHAVING -
SELECT s.year, s.teamid, count(*) AS NUMBER_OF_PLAYERS FROM scoring s WHERE s.year = 2011 GROUP BY s.year, s.teamid; YEAR TEAMID NUMBER_OF_PLAYERS ----- ------- ------------------ 2011 MTL 34 2011 CAL 40 2011 CBS 42 2011 PHO 35 2011 NYI 36 ... SELECT s.year, s.teamid, count(*) AS NUMBER_OF_PLAYERS FROM scoring s WHERE s.year = 2011 GROUP BY s.year, s.teamid HAVING count(*) > 40; YEAR TEAMID NUMBER_OF_PLAYERS ----- ------- ------------------ 2011 CBS 42 2011 MIN 47 2011 FLO 41 - Example 10:
SELECTstatement showingUNION ALLcompared with usingUNION DISTINCT -
The player with playerid = macinst01 is included in the result set of both
SELECTstatements of theUNION. Therefore, theUNION ALLstatement returns this player twice, once for eachSELECTstatement. TheUNION DISTINCTeliminates duplicate rows from the combined result set.SELECT playerid, firstname, lastname, height, weight FROM players WHERE playerid = 'macinst01' UNION ALL SELECT playerid, firstname, lastname, height, weight FROM players WHERE weight > 260; PLAYERID FIRSTNAME LASTNAME HEIGHT WEIGHT --------- ---------- --------- ------- ------- macinst01 Steve MacIntyre 78 265 byfugdu01 Dustin Byfuglien 75 265 ivanara01 Raitis Ivanans 75 263 macinst01 Steve MacIntyre 78 265 SELECT playerid, firstname, lastname, height, weight FROM players WHERE playerid = 'macinst01' UNION DISTINCT SELECT playerid, firstname, lastname, height, weight FROM players WHERE weight > 260; PLAYERID FIRSTNAME LASTNAME HEIGHT WEIGHT --------- ---------- --------- ------- ------- macinst01 Steve MacIntyre 78 265 byfugdu01 Dustin Byfuglien 75 265 ivanara01 Raitis Ivanans 75 263 - Example 11:
SELECTstatement usingORDER BY -
Ordering the result set of a
SELECTstatement.SELECT playerid, firstname, lastname, height, weight FROM players WHERE weight > 260 ORDER BY lastname; PLAYERID FIRSTNAME LASTNAME HEIGHT WEIGHT --------- ---------- --------- ------- ------- byfugdu01 Dustin Byfuglien 75 265 ivanara01 Raitis Ivanans 75 263 macinst01 Steve MacIntyre 78 265Ordering the combined result set of a
UNIONquery.SELECT playerid, firstname, lastname AS lname, height, weight FROM players WHERE playerid like 'zo%' UNION ALL SELECT playerid, firstname, lastname AS lname, height, weight FROM players WHERE playerid like 'un%' ORDER BY firstname; PLAYERID FIRSTNAME LNAME HEIGHT WEIGHT --------- ---------- ----------- ------- ------- ungerga01 Garry Unger 71 170 zolniha01 Harry Zolnierczyk 71 160 zoborma01 Marty Zoborosky 70 180 underma01 Matt Underhill 74 195 zombori01 Rick Zombo 73 202The result set of each individual
SELECTstatement in aUNIONcan be sorted independently. In this case, eachSELECTstatement selects from a derived table that is created from each individualSELECTstatement.SELECT * FROM (SELECT playerid, firstname, lastname AS lname, height, weight FROM players WHERE playerid like 'zo%' ORDER BY firstname) a UNION SELECT * FROM (SELECT playerid, firstname, lastname AS lname, height, weight FROM players WHERE playerid like 'un%' ORDER BY firstname) b; PLAYERID FIRSTNAME LNAME HEIGHT WEIGHT --------- ---------- ----------- ------- ------- zolniha01 Harry Zolnierczyk 71 160 zoborma01 Marty Zoborosky 70 180 zombori01 Rick Zombo 73 202 ungerga01 Garry Unger 71 170 underma01 Matt Underhill 74 195 - Example 12: Defining a collation type as an
ORDER BYoption -
DROP TABLE tst_table IF EXISTS; CREATE TABLE tst_table (column1 VARCHAR(12)); INSERT INTO tst_table VALUES ('abc'),('ABC'); INSERT INTO tst_table VALUES ('bcd'),('BCD'); SELECT * FROM tst_table ORDER BY column1; COLUMN1 -------- ABC BCD abc bcd SELECT * FROM tst_table ORDER BY column1 COLLATE case_insensitive; COLUMN1 -------- abc ABC bcd BCD SELECT * FROM tst_table ORDER BY column1 COLLATE case_insensitive DESC; COLUMN1 -------- bcd BCD abc ABC - Example 13:
SELECTstatement usingLIMIT,FETCH,OFFSET -
SELECT name AS teamname, conferenceid, divisionid, rank, wins||'-'||losses||'-'||ties AS RECORD FROM teams WHERE year = 2009 ORDER BY rank, conferenceid, divisionid LIMIT 10; TEAMNAME CONFERENCEID DIVISIONID RANK RECORD ------------------- ------------- ----------- ----- ------- New Jersey Devils EC AT 1 48-27-0 Buffalo Sabres EC NE 1 45-27-0 Washington Capitals EC SE 1 54-15-0 Chicago Blackhawks WC CE 1 52-22-0 Vancouver Canucks WC NW 1 49-28-0 San Jose Sharks WC PC 1 51-20-0 Pittsburgh Penguins EC AT 2 47-28-0 Ottawa Senators EC NE 2 44-32-0 Atlanta Thrashers EC SE 2 35-34-0 Detroit Red Wings WC CE 2 44-24-0 SELECT name AS teamname, conferenceid, divisionid, rank, wins||'-'||losses||'-'||ties AS RECORD FROM teams WHERE year = 2009 ORDER BY rank, conferenceid, divisionid FETCH FIRST 3; TEAMNAME CONFERENCEID DIVISIONID RANK RECORD ------------------- ------------- ----------- ----- ------- New Jersey Devils EC AT 1 48-27-0 Buffalo Sabres EC NE 1 45-27-0 Washington Capitals EC SE 1 54-15-0 SELECT name AS teamname, conferenceid, divisionid, rank, wins||'-'||losses||'-'||ties AS RECORD FROM teams WHERE year = 2009 ORDER BY rank, conferenceid, divisionid LIMIT 10 OFFSET 2; TEAMNAME CONFERENCEID DIVISIONID RANK RECORD ------------------- ------------- ----------- ----- ------- Washington Capitals EC SE 1 54-15-0 Chicago Blackhawks WC CE 1 52-22-0 Vancouver Canucks WC NW 1 49-28-0 San Jose Sharks WC PC 1 51-20-0 Pittsburgh Penguins EC AT 2 47-28-0 Ottawa Senators EC NE 2 44-32-0 Atlanta Thrashers EC SE 2 35-34-0 Detroit Red Wings WC CE 2 44-24-0 Colorado Avalanche WC NW 2 43-30-0 Phoenix Coyotes WC PC 2 50-25-0 SELECT name AS teamname, conferenceid, divisionid, rank, wins||'-'||losses||'-'||ties AS RECORD FROM teams WHERE year = 2009 ORDER BY rank, conferenceid, divisionid LIMIT 2,10; TEAMNAME CONFERENCEID DIVISIONID RANK RECORD ------------------- ------------- ----------- ----- ------- Washington Capitals EC SE 1 54-15-0 Chicago Blackhawks WC CE 1 52-22-0 Vancouver Canucks WC NW 1 49-28-0 San Jose Sharks WC PC 1 51-20-0 Pittsburgh Penguins EC AT 2 47-28-0 Ottawa Senators EC NE 2 44-32-0 Atlanta Thrashers EC SE 2 35-34-0 Detroit Red Wings WC CE 2 44-24-0 Colorado Avalanche WC NW 2 43-30-0 Phoenix Coyotes WC PC 2 50-25-0 SELECT name AS teamname, conferenceid, divisionid, rank, wins||'-'||losses||'-'||ties AS RECORD FROM teams WHERE year = 2009 ORDER BY rank, conferenceid, divisionid OFFSET 2 FETCH NEXT 4; TEAMNAME CONFERENCEID DIVISIONID RANK RECORD ------------------- ------------- ----------- ----- ------- Washington Capitals EC SE 1 54-15-0 Chicago Blackhawks WC CE 1 52-22-0 Vancouver Canucks WC NW 1 49-28-0 San Jose Sharks WC PC 1 51-20-0 - Example 14: Result set column order for a
USINGjoin -
Using an asterisk (“
*”) for the select column list, the result set returns all columns in both tables (or views, derived tables, etc.) in the order they appear in the table, returning columns from the first table and then the second table. When joined withUSINGthe result set column list is different. To reduce the number of columns in the result set, this example will use views created from tables that are generated by the QuickStart demo./* Create the views to be used for this example */ CREATE VIEW vw_players AS SELECT playerid,firstname,lastname FROM players; CREATE VIEW vw_scoring AS SELECT playerid,year,stint,teamid,position FROM scoring; /* SELECT using JOIN of the above two views. The first three columns are from */ vw_players, the next five columns are from vw_scoring */ SELECT * FROM vw_players p JOIN vw_scoring s ON p.playerid = s.playerid WHERE s.position = 'G' AND s.year = 1975 ORDER BY p.playerid; PLAYERID FIRSTNAME LASTNAME PLAYERID YEAR STINT TEAMID POSITION --------- ---------- ----------- --------- ----- ------ ------- --------- abrahch01 Christer Abrahamsson abrahch01 1975 1 NEW G aubryse01 Serge Aubry aubryse01 1975 1 CIN G belanyv01 Yves Belanger belanyv01 1975 1 STL G belhumi01 Michel Belhumeur belhumi01 1975 1 WAS G ... /* Now JOIN with USING on common column playerid. The result set column list is reduced by one column, the playerid, which is the column specified as USING. USING columns appear only once in the column list of the result set. The remaining columns are ordered the same as they appear in the tables. The columns from the first table listed in the JOIN appear first. */ SELECT * FROM vw_players p JOIN vw_scoring s USING (playerid) WHERE s.position = 'G' AND s.year = 1975 ORDER BY p.playerid; PLAYERID FIRSTNAME LASTNAME YEAR STINT TEAMID POSITION --------- ---------- ----------- ----- ------ ------- --------- abrahch01 Christer Abrahamsson 1975 1 NEW G aubryse01 Serge Aubry 1975 1 CIN G belanyv01 Yves Belanger 1975 1 STL G belhumi01 Michel Belhumeur 1975 1 WAS G ... - Example 15:
USE_INDEXOptimizer Hint -
CREATE TABLE foo (a INTEGER, b INTEGER, c INTEGER, d INTEGER); CREATE INDEX foo_a ON foo(a); CREATE INDEX foo_b ON foo(b); CREATE INDEX foo_c ON foo(c); CREATE INDEX foo_d ON foo(d); -- Choose a specified index; the optimizer has the freedom to choose -- a streamed / bitmap scan over the specified index. SELECT /*+ USE_INDEX(foo, foo_a) */ * FROM foo WHERE a > 100 ORDER BY a; -- Choose a streamed index SELECT /*+ USE_INDEX(foo, KEY_ORDERED foo_a) */ * FROM foo WHERE a > 100 ORDER BY a; -- Choose a bitmap index SELECT /*+ USE_INDEX(foo, ID_ORDERED foo_a) */ * FROM foo WHERE a > 100 ORDER BY a; -- Choose a streamed index SELECT /*+ USE_INDEX(foo, KEY_ORDERED foo_a) */ * FROM foo WHERE a > 100 AND b > 100 ORDER BY a; -- Choose a bitmap index SELECT /*+ USE_INDEX (foo, ID_ORDERED foo_b) */ * FROM foo WHERE a > 100 AND b > 100 ORDER BY a; -- Consider: streamed foo_a, bitmap foo_b SELECT /*+ USE_INDEX(foo, KEY_ORDERED foo_a, ID_ORDERED foo_b) */ * FROM foo WHERE a > 100 AND b > 100 ORDER BY a; -- Consider only streamed scans over foo_a and foo_b SELECT /*+ USE_INDEX(foo, KEY_ORDERED foo_a, KEY_ORDERED foo_b) */ * FROM foo WHERE a > 100 AND b > 100 ORDER BY a; -- Consider: bitmap foo_a, bitmap foo_b, BitmapAND(bitmap foo_a, bitmap foo_b) SELECT /*+ USE_INDEX(foo, ID_ORDERED foo_a, ID_ORDERED foo_b) */ * FROM foo WHERE a > 100 AND b > 100 ORDER BY a; -- Let the optimizer choose an optimal IIU plan over foo_a and foo_b SELECT /*+ USE_INDEX(foo, foo_a, foo_b) */ * FROM foo WHERE a > 100 AND b > 100 ORDER BY a; -- Use a streamed index (even though there is no group by/ORDER BY) SELECT /*+ USE_INDEX(foo, KEY_ORDERED foo_a) */ * FROM foo WHERE a > 100 AND b > 100; -- In the context of joins CREATE TABLE bar (a INTEGER, b INTEGER, c INTEGER, d INTEGER); SELECT /*+ USE_INDEX(foo, foo_a) */ * FROM foo, bar WHERE foo.a = bar.b AND foo.a > 100 AND bar.b > 100; -- In the context of joins (with indexes ON both tables) CREATE INDEX bar_b ON bar(b); SELECT /*+ USE_INDEX(foo, foo_a), USE_INDEX(bar, bar_b) */ * FROM foo, bar WHERE foo.a = bar.b AND foo.a > 100 AND bar.b > 100; -- With joins and a group by (specify both ordered and index hints) SELECT /*+ ordered, USE_INDEX(foo, KEY_ORDERED foo_a) */ foo.a FROM foo, bar WHERE foo.a = bar.b AND foo.a > 100 AND bar.b > 100 GROUP BY foo.a; -- With joins and an ORDER BY (specify both ordered and index hints) SELECT /*+ ordered, USE_INDEX (foo, KEY_ORDERED foo_a) */ * FROM foo, bar WHERE foo.a = bar.b AND foo.a > 100 AND bar.b > 100 ORDER BY foo.a; - Example 16:
SKIP_INDEXOptimizer Hint -
CREATE TABLE foo (a INTEGER, b INTEGER, c INTEGER, d INTEGER); CREATE INDEX foo_a ON foo(a); CREATE INDEX foo_b ON foo(b); CREATE INDEX foo_c ON foo(c); CREATE INDEX foo_d ON foo(d); -- Do not choose index 'foo_a' SELECT /*+ SKIP_INDEX(foo, foo_a) */ * FROM foo WHERE a > 100 ORDER BY a; -- Do not choose a streamed scan over foo_a; the optimizer can choose a -- bitmap scan over foo_a. SELECT /*+ SKIP_INDEX(foo, KEY_ORDERED foo_a) */ * FROM foo WHERE a > 100 ORDER BY a; -- Do not choose a bitmap scan over foo_a; the optimizer can choose a -- streamed scan over foo_a SELECT /*+ SKIP_INDEX(foo, ID_ORDERED foo_a) */ * FROM foo WHERE a > 100 ORDER BY a; -- Equivalent to /*+ SKIP_INDEX(foo foo_a) */ SELECT /*+ SKIP_INDEX(foo, KEY_ORDERED foo_a, ID_ORDERED foo_a) */ * FROM foo WHERE a > 100 ORDER BY a; -- Do not consider streamed scans over foo_a and foo_b SELECT /*+ SKIP_INDEX(foo, KEY_ORDERED foo_a, ID_ORDERED foo_b) */ * FROM foo WHERE a > 100 AND b > 100 ORDER BY a; -- In the context of joins SELECT /*+ SKIP_INDEX(foo, foo_a) */ * FROM foo, bar WHERE foo.a = bar.b AND foo.a > 100 AND bar.b > 100; -- In the context of joins; do not use an index only ON the specified instance of foo SELECT /*+ SKIP_INDEX(foo_inst_a, foo_a) */ * FROM foo as foo_inst_a, foo as foo_inst_b WHERE foo_inst_a.a = foo_inst_b.a AND foo_inst_a.a > 50 AND foo_inst_b.a < 100; -- In the context of joins SELECT /*+ ordered, SKIP_INDEX(foo, KEY_ORDERED foo_a) */ foo.a FROM foo, bar WHERE foo.a = bar.b AND foo.a > 100 AND bar.b > 100 GROUP BY foo.a; -- In the context of joins SELECT /*+ ordered, SKIP_INDEX(foo, foo_a) */ * FROM foo, bar WHERE foo.a = bar.b AND foo.a > 100 AND bar.b > 100 ORDER BY foo.a; - Example 17:
ROWNUM() -
With the exception of an
ORDER BYorGROUP BYclause, this unique identifier returned byROWNUM()will always be sequential.DROP TABLE IF EXISTS hockey_dup; CREATE TABLE hockey_dup ( id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY, number INTEGER, name STRING, position STRING ); INSERT INTO hockey_dup (number,name,position) SELECT number,name,position FROM hockey WHERE name like 'A%' or name like 'D%'; SELECT id,number,name,position,rownum() FROM hockey_dup; ID NUMBER NAME POSITION ROWNUM --- ------- ----------------- --------- ------- 1 46 DAVID KREJCI Forward 1 2 20 DANIEL PAILLE Forward 2 3 21 ANDREW FERENCE Defense 3 4 27 DOUGIE HAMILTON Defense 4 5 45 AARON JOHNSON Defense 5 6 54 ADAM MCQUAID Defense 6 7 44 DENNIS SEIDENBERG Defense 7 8 35 ANTON KHUDOBIN Goalie 8 /* delete a row which will reset what the ROWNUM() function returns */ DELETE FROM hockey_dup WHERE id = 6; SELECT id,number,name,position,rownum() FROM hockey_dup; ID NUMBER NAME POSITION ROWNUM --- ------- ----------------- --------- ------- 1 46 DAVID KREJCI Forward 1 2 20 DANIEL PAILLE Forward 2 3 21 ANDREW FERENCE Defense 3 4 27 DOUGIE HAMILTON Defense 4 5 45 AARON JOHNSON Defense 5 7 44 DENNIS SEIDENBERG Defense 6 8 35 ANTON KHUDOBIN Goalie 7 /* add a predicate that will change the position of some rows in the result set */ SELECT id,number,name,position,record_number,rownum() FROM hockey_dup WHERE name LIKE 'D%'; ID NUMBER NAME POSITION RECORD_NUMBER ROWNUM --- ------- ----------------- --------- -------------- ------- 1 46 DAVID KREJCI Forward 1 1 2 20 DANIEL PAILLE Forward 2 2 4 27 DOUGIE HAMILTON Defense 4 3 7 44 DENNIS SEIDENBERG Defense 7 4 SELECT id,number,name,position,rownum() FROM hockey_dup WHERE name LIKE 'D%'; ID NUMBER NAME POSITION ROWNUM --- ------- ----------------- --------- ------- 1 46 DAVID KREJCI Forward 1 2 20 DANIEL PAILLE Forward 2 4 27 DOUGIE HAMILTON Defense 3 7 44 DENNIS SEIDENBERG Defense 4 /* since the rownum() function returns its identifier before any ORDER BY, the rownum() value is not always sequential */ SELECT id, number,name,position,rownum() FROM hockey_dup WHERE name LIKE 'D%' ORDER BY name; ID NUMBER NAME POSITION ROWNUM --- ------- ----------------- --------- ------- 2 20 DANIEL PAILLE Forward 2 1 46 DAVID KREJCI Forward 1 7 44 DENNIS SEIDENBERG Defense 4 4 27 DOUGIE HAMILTON Defense 3