MS SQL Server un MS Access SQL valodas dialekts

advertisement
1
MS SQL Server SQL valodas dialekts
1. MS Access datu bāzes Jet un MS Database Engine.
2. MS Accessizmantošana lietojumu veidošanai priekš MS SQL Server.
3. MS Access un MS SQL Server SQL valodas dialekti.
4. Select tipa vaicājumu iespēju apskats.
4.1. Vienkārši vaicājumi vienai tabulai, atlasot kolonas (laukus) un rindas.
4.2. Vienkārši vaicājumi vairākām tabulām, atlasot kolonas (laukus) un
rindas.
4.3. Aprēķinu kolonu (lauku) veidošana, kolonu nosaukumu norāde.
4.4. Atbildes dublējošo rindu izslēgšana lietojot DISTINCT.
4.5. LIKE izmantošana.
4.6. Vienkārši pakārtotie vaicājumi (subqueries):
- SELECT rindā;
- FROM rindā;
- WHERE rindā.
4.7. EXISTS un NOT EXISTS izmantošana.
4.8. Korelētie pakārtotie vaivājumi.
4.9. Grupēšanas GROUP BY lietošana.
4.10. GROUP BY lietošana ar aprēķinu izteiksmi.
4.11. GROUP BY ALL izmantošana.
4.12. ORDER BY izmantošana.
4.13. Grupu noteikumu norāde ar HAVING.
4.14. Pakārtotie vaicājumi HAVING rindā.
4.15. Grupu agregātvērtību aprēķins lietojot COMPUTE un COMPUTE
BY.
4.16. Vairāku COMPUTE klauzulu izmantošana.
4.17. GROUP BY un COMPUTE salīdzinājums.
4.18. Klauzulas CUBE lietošana.
4.19. Funkcijas GROUPING izmantošana.
4.20. GROUPING funkcijas lietošana ar klauzulu CUBE.
4.21. ROLLUP operatora lietošana.
4.22. Norāžu optimizatoram izmantošana:
- INDEX norāde;
- GROUP norāde;
- UNION darbības norādes.
4.23. Jaunu tabulu veidošana ar SELECT INTO.
5. MS SQL Server SQL valodas paplāšinājums Transact SQL.
5.1. Transact SQL valodas mainīgie.
2
5.2. Transact SQL valodas operatori.
5.2. Transact SQL vadības konstrukcijas.
5.3. Kursoru tipi (statiskie, slēdža tipa, virknes, dināmiskie).
5.4. Kursoru lietošana datu izgūšanai no datu bāzes.
5.5. MS SQL Server funkcijas.
5.6. SQL vaicājumu realizēšana Transact SQL vidē.
6. Datu noliktavas, datu vitrīnas un daudzdimensiju vaicājumu valoda
(Multidimensional Expresion Language – MXL).
6.1 MXL vispārējā sintakse.
6.2. MXL funkcijas.
6.3. MXL vaicājumu tipi.
7. ADO objektu izmantošana datu izguvei no dažādiem avotiem.
3
Select tipa vaicājumi
SELECT [ ALL | DISTINCT ] [ TOP integer | TOP integer PERCENT ]
[WITH TIES ] select_saraksts [ INTO jauna_tabula ]
FROM tabulveida_datu_avoti
WHERE ierakstu_meklēšanas_noteikumi
GROUP BY [ALL] ierakstu_grupēšanas_noteikumi [ WITH { CUBE |
ROLLUP }]
HAVING ierakstu_grupas_atlases_noteikumi
ORDER BY ierakstu_šķirošanas_noteikumi [ ASC | DESC ]
[ COMPUTE { { AVG | COUNT | MAX | MIN | SUM } ( expression ) } [ ,...n ]
[ BY expression [ ,...n ] ] ]
[ FOR { BROWSE | XML { RAW | AUTO | EXPLICIT }
[ , XMLDATA ]
[ , ELEMENTS ]
[ , BINARY base64 ] } ]
[ OPTION ( < query_hint > [ ,...n ]) ]
SELECT_tipa_vaicājums
UNION [ ALL ]
SELECT_tipa_vaicājums
4
SELECT Clause
Specifies the columns to be returned by the query.
SELECT [ ALL | DISTINCT ]
[ TOP n [ PERCENT ] [ WITH TIES ] ]
< select_list >
< select_list > ::=
{ *
| { table_name | view_name | table_alias }.*
| { column_name | expression | IDENTITYCOL | ROWGUIDCOL }
[ [ AS ] column_alias ]
| column_alias = expression
} [ ,...n ]
ALL
Specifies that duplicate rows can appear in the result set. ALL is the default.
DISTINCT
Specifies that only unique rows can appear in the result set. Null values are considered equal for the
purposes of the DISTINCT keyword.
TOP n [PERCENT]
Specifies that only the first n rows are to be output from the query result set. n is an integer between
0 and 4294967295. If PERCENT is also specified, only the first n percent of the rows are output
from the result set. When specified with PERCENT, n must be an integer between 0 and 100.
If the query includes an ORDER BY clause, the first n rows (or n percent of rows) ordered by the
ORDER BY clause are output. If the query has no ORDER BY clause, the order of the rows is
arbitrary.
WITH TIES
Specifies that additional rows be returned from the base result set with the same value in the
ORDER BY columns appearing as the last of the TOP n (PERCENT) rows. TOP ...WITH TIES can
only be specified if an ORDER BY clause is specified.
< select_list >
The columns to be selected for the result set. The select list is a series of expressions separated by
commas.
*
Specifies that all columns from all tables and views in the FROM clause should be returned. The
columns are returned by table or view, as specified in the FROM clause, and in the order in which
they exist in the table or view.
table_name | view_name | table_alias.*
Limits the scope of the * to the specified table or view.
5
column_name
Is the name of a column to return. Qualify column_name to prevent an ambiguous reference, such
as occurs when two tables in the FROM clause have columns with duplicate names. For example,
the Customers and Orders tables in the Northwind database both have a column named
ColumnID. If the two tables are joined in a query, the customer ID can be specified in the select list
as Customers.CustomerID.
expression
Is a column name, constant, function, any combination of column names, constants, and functions
connected by an operator(s), or a subquery.
IDENTITYCOL
Returns the identity column. If the more than one table in the FROM clause has a column with the
IDENTITY property, IDENTITYCOL must be qualified with the specific table name, such as
T1.IDENTITYCOL.
ROWGUIDCOL
Returns the row global unique identifier column. If the more than one table in the FROM clause
with the ROWGUIDCOL property, ROWGUIDCOL must be qualified with the specific table
name, such as T1.ROWGUIDCOL.
column_alias
Is an alternative name to replace the column name in the query result set. For example, an alias such
as "Quantity", or "Quantity to Date", or "Qty" can be specified for a column named quantity.
Aliases are used also to specify names for the results of expressions, for example:
USE Northwind
SELECT AVG(UnitPrice) AS 'Average Price'
FROM [Order Details]
column_alias can be used in an ORDER BY clause. However, it cannot be used in a WHERE,
GROUP BY, or HAVING clause. If the query expression is part of a DECLARE CURSOR
statement, column_alias cannot be used in the FOR UPDATE clause.
6
INTO Clause
Creates a new table and inserts the resulting rows from the query into it.
The user executing a SELECT statement with the INTO clause must have CREATE TABLE
permission in the destination database. SELECT...INTO cannot be used with the COMPUTE. You
can use SELECT...INTO to create an identical table definition (different table name) with no data
by having a FALSE condition in the WHERE clause.
[ INTO new_table ]
new_table
Specifies the name of a new table to be created, based on the columns in the select list and the rows
chosen by the WHERE clause. The format of new_table is determined by evaluating the
expressions in the select list. The columns in new_table are created in the order specified by the
select list. Each column in new_table has the same name, data type, and value as the corresponding
expression in the select list.
When a computed column is included in the select list, the corresponding column in the new table is
not a computed column. The values in the new column are the values that were computed at the
time SELECT...INTO was executed.
In this release of SQL Server, the select into/bulkcopy database option has no effect on whether
you can create a permanent table with SELECT INTO. The amount of logging for certain bulk
operations, including SELECT INTO, depends on the recovery model in effect for the database. In
previous releases, creating a permanent table with SELECT INTO was allowed only if select
into/bulkcopy was set.
select into/bulkcopy is available for backward compatibility purposes, but may not be supported in
future releases.
7
FROM Clause
Specifies the table(s) from which to retrieve rows. The FROM clause is required except when the
select list contains only constants, variables, and arithmetic expressions (no column names).
[ FROM { < table_source > } [ ,...n ] ]
< table_source > ::=
table_name [ [ AS ] table_alias ] [ WITH ( < table_hint > [ ,...n ] ) ]
| view_name [ [ AS ] table_alias ]
| rowset_function [ [ AS ] table_alias ]
| OPENXML
| derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ]
| < joined_table >
< joined_table > ::=
< table_source > < join_type > < table_source > ON < search_condition >
| < table_source > CROSS JOIN < table_source >
| < joined_table >
< join_type > ::=
[ INNER | { { LEFT | RIGHT | FULL } [ OUTER ] } ]
[ < join_hint > ]
JOIN
< table_source >
Specifies tables, views, derived tables, and joined tables for the SELECT statement.
table_name [ [ AS ] table_alias ]
Specifies the name of a table and an optional alias.
view_name [ [ AS ] table_alias ]
Specifies the name, a view, and an optional alias.
rowset_function [ [ AS ] table_alias ]
Is the name of a rowset function and an optional alias
OPENXML
Provides rowset view over an XML document.
WITH ( < table_hint > [ ,...n ] )
Specifies one or more table hints.
derived_table [ [ AS ] table_alias ]
Is a nested SELECT statement, retrieving rows from the specified database and table(s).
column_alias
Is an optional alias to replace a column name in the result set.
< joined_table >
Is a result set that is the product of two or more tables. For example:
SELECT *
FROM tab1 LEFT OUTER JOIN tab2 ON tab1.c3 = tab2.c3
RIGHT OUTER JOIN tab3 LEFT OUTER JOIN tab4
ON tab3.c1 = tab4.c1
ON tab2.c3 = tab4.c3
8
For multiple CROSS joins, use parentheses to change the natural order of the joins.
< join_type >
Specifies the type of join operation.
INNER
Specifies that all matching pairs of rows are returned. Discards unmatched rows from both
tables. This is the default if no join type is specified.
LEFT [ OUTER ]
Specifies that all rows from the left table not meeting the specified condition are included in
the result set in addition to all rows returned by the inner join. Output columns from the left
table are set to NULL.
RIGHT [ OUTER ]
Specifies that all rows from the right table not meeting the specified condition are included
in the result set in addition to all rows returned by the inner join. Output columns from the
right table are set to NULL.
FULL [ OUTER ]
If a row from either the left or right table does not match the selection criteria, specifies the
row be included in the result set, and output columns that correspond to the other table be
set to NULL. This is in addition to all rows usually returned by the inner join.
< join_hint >
Specifies a join hint or execution algorithm. If <join_hint> is specified, INNER, LEFT,
RIGHT, or FULL must also be explicitly specified.
JOIN
Indicates that the specified tables or views should be joined.
ON < search_condition >
Specifies the condition on which the join is based. The condition can specify any predicate,
although columns and comparison operators are often used. For example:
SELECT ProductID, Suppliers.SupplierID
FROM Suppliers JOIN Products
ON (Suppliers.SupplierID = Products.SupplierID)
When the condition specifies columns, the columns do not have to have the same name or same
data type. However, if the data types are not identical, they must be either compatible or types that
Microsoft® SQL Server™ can implicitly convert. If the data types cannot be implicitly converted,
the condition must explicitly convert the data type using the CAST function.
CROSS JOIN (Dekarta reizinājums)
Specifies the cross-product of two tables. Returns the same rows as if the tables to be joined were
simply listed in the FROM clause and no WHERE clause was specified. For example, both of these
queries return a result set that is a cross join of all the rows in T1 and T2:
SELECT * FROM T1, T2
SELECT * FROM T1 CROSS JOIN T2
9
WHERE Clause
Specifies a search condition to restrict the rows returned.
[ WHERE < search_condition > | < old_outer_join > ]
< old_outer_join > ::=
column_name { * = | = * } column_name
< search_condition >
Restricts the rows returned in the result set through the use of predicates. There is no limit to the
number of predicates that can be included in a search condition.
< old_outer_join >
Specifies an outer join using the nonstandard product-specific syntax and the WHERE clause. The
*= operator is used to specify a left outer join and the =* operator is used to specify a right outer
join.
This example specifies a left outer join in which the rows from Tab1, that do not meet the specified
condition, are included in the result set:
SELECT Tab1.name, Tab2.id
FROM Tab1, Tab2
WHERE Tab1.id *=Tab2.id
Note Using this syntax for outer joins is discouraged because of the potential for ambiguous
interpretation and because it is nonstandard. Instead, specify joins in the FROM clause.
It is possible to specify outer joins by using join operators in the FROM clause or by using the nonstandard *= and =* operators in the WHERE clause. The two methods cannot both be used in the
same statement.
10
GROUP BY Clause
Specifies the groups into which output rows are to be placed and, if aggregate functions are
included in the SELECT clause <select list>, calculates a summary value for each group. When
GROUP BY is specified, either each column in any non-aggregate expression in the select list
should be included in the GROUP BY list, or the GROUP BY expression must match exactly the
select list expression.
If the ORDER BY clause is not specified, groups returned using the GROUP BY clause are not in
any particular order. It is recommended that you always use the ORDER BY clause to specify a
particular ordering of the data.
[ GROUP BY [ ALL ] group_by_expression [ ,...n ] [ WITH { CUBE | ROLLUP } ] ]
ALL
Includes all groups and result sets, even those that do not have any rows that meet the search
condition specified in the WHERE clause. When ALL is specified, null values are returned for the
summary columns of groups that do not meet the search condition. You cannot specify ALL with
the CUBE or ROLLUP operators.
GROUP BY ALL is not supported in queries that access remote tables if there is also a WHERE
clause in the query.
group_by_expression
Is an expression on which grouping is performed. group_by_expression is also known as a grouping
column. group_by expression can be a column or a nonaggregate expression that references a
column. A column alias that is defined in the select list cannot be used to specify a grouping
column.
Columns of type text, ntext, and image cannot be used in group_by_expression.
For GROUP BY clauses that do not contain CUBE or ROLLUP, the number of
group_by_expression items is limited by the GROUP BY column sizes, the aggregated columns,
and the aggregate values involved in the query. This limit originates from the limit of 8,060 bytes
on the intermediate work table that is needed to hold intermediate query results. A maximum of 10
grouping expressions is permitted when CUBE or ROLLUP is specified.
CUBE
Specifies that in addition to the usual rows provided by GROUP BY, summary rows are introduced
into the result set. A GROUP BY summary row is returned for every possible combination of group
and subgroup in the result set. A GROUP BY summary row is displayed as NULL in the result, but
is used to indicate all values. Use the GROUPING function to determine whether null values in the
result set are GROUP BY summary values.
The number of summary rows in the result set is determined by the number of columns included in
the GROUP BY clause. Each operand (column) in the GROUP BY clause is bound under the
grouping NULL and grouping is applied to all other operands (columns). Because CUBE returns
every possible combination of group and subgroup, the number of rows is the same, regardless of
the order in which the grouping columns are specified.
ROLLUP
Specifies that in addition to the usual rows provided by GROUP BY, summary rows are introduced
into the result set. Groups are summarized in a hierarchical order, from the lowest level in the group
to the highest. The group hierarchy is determined by the order in which the grouping columns are
specified. Changing the order of the grouping columns can affect the number of rows produced in
the result set.
Distinct aggregates, for example, AVG(DISTINCT column_name), COUNT(DISTINCT
column_name), and SUM(DISTINCT column_name), are not supported when using CUBE or
ROLLUP. If used, SQL Server returns an error message and cancels the query.
11
Datu tabula Darbinieki
DARB_NUM DZIMUMS AMATS
1
sieviete
sekretāre
2
vīrietis
IT speciālists
3
sieviete
sekretāre
4
vīrietis
IT speciālists
5
vīrietis
analītiķis
6
sieviete
analītiķis
7
sieviete
analītiķis
ALGA
200
250
210
260
200
300
350
1. vaicājuma piemērs ar GROUP BY.
SELECT DZIMUMS, AMATS, SUM(ALGA) Summa
FROM Darbinieki
GROUP BY DZIMUMS, AMATS;
2. vaicājuma piemērs ar CUBE.
SELECT DZIMUMS, AMATS, SUM(ALGA) Summa
FROM Darbinieki
GROUP BY DZIMUMS, AMATS WITH CUBE;
3. vaicājuma piemērs ar ROLLUP
SELECT DZIMUMS, AMATS, SUM(ALGA) Summa
FROM Darbinieki
GROUP BY DZIMUMS, AMATS WITH ROLLUP;
DZIMUMS
sieviete
vīrietis
vīrietis
sieviete
AMATS
sekretāre
IT speciālists
analītiķis
analītiķis
Summa
410
510
200
650
DZIMUMS
sieviete
sieviete
sieviete
vīrietis
vīrietis
vīrietis
NULL
NULL
NULL
NULL
AMATS
sekretāre
analītiķis
NULL
IT speciālists
analītiķis
NULL
NULL
sekretāre
analītiķis
IT speciālists
Summa
410
650
1060
510
200
710
3540
410
850
510
DZIMUMS
sieviete
sieviete
sieviete
vīrietis
vīrietis
vīrietis
NULL
4. vaicājuma piemērs ar funkciju GROUPING.
SELECT DZIMUMS, AMATS, SUM(ALGA) AS Summa,
GROUPING(DZIMUMS) AS Dz, GROUPING(AMATS) AS Am
FROM Darbinieki
GROUP BY DZIMUMS, AMATS WITH ROLLUP;
DZIMUMS
sieviete
sieviete
sieviete
vīrietis
vīrietis
vīrietis
NULL
AMATS
sekretāre
analītiķis
NULL
IT speciālists
analītiķis
NULL
NULL
Summa
410
650
1060
510
200
710
3540
Dz
0
0
0
0
0
0
1
Am
0
0
1
0
0
1
1
AMATS
sekretāre
analītiķis
NULL
IT speciālists
analītiķis
NULL
NULL
Summa
410
650
1060
510
200
710
3540
12
HAVING Clause
Specifies a search condition for a group or an aggregate. HAVING is usually used with the GROUP
BY clause. When GROUP BY is not used, HAVING behaves like a WHERE clause.
[ HAVING < search_condition > ]
< search_condition >
Specifies the search condition for the group or the aggregate to meet. When HAVING is used with
GROUP BY ALL, the HAVING clause overrides ALL. The text, image, and ntext data types
cannot be used in a HAVING clause.
Note Using the HAVING clause in the SELECT statement does not affect the way the CUBE
operator groups the result set and returns summary aggregate rows.
13
Search Condition
Is a combination of one or more predicates using the logical operators AND, OR, and NOT.
< search_condition > ::=
{ [ NOT ] < predicate > | ( < search_condition > ) }
[ { AND | OR } [ NOT ] { < predicate > | ( < search_condition > ) } ]
} [ ,...n ]
< predicate > ::=
{ expression { = | < > | ! = | > | > = | ! > | < | < = | ! < } expression
| string_expression [ NOT ] LIKE string_expression
[ ESCAPE 'escape_character' ]
| expression [ NOT ] BETWEEN expression AND expression
| expression IS [ NOT ] NULL
| CONTAINS
( { column | * } , '< contains_search_condition >' )
| FREETEXT ( { column | * } , 'freetext_string' )
| expression [ NOT ] IN ( subquery | expression [ ,...n ] )
| expression { = | < > | ! = | > | > = | ! > | < | < = | ! < }
{ ALL | SOME | ANY} ( subquery )
| EXISTS ( subquery )
}
< search_condition >
Specifies the conditions for the rows returned in the result set for a SELECT statement, query
expression, or subquery. For an UPDATE statement, specifies the rows to be updated. For a
DELETE statement, specifies the rows to be deleted. There is no limit to the number of predicates
that can be included in a Transact-SQL statement search condition.
NOT Negates the Boolean expression specified by the predicate.
AND Combines two conditions and evaluates to TRUE when both of the conditions are TRUE.
OR
Combines two conditions and evaluates to TRUE when either condition is TRUE.
< predicate > Is an expression that returns TRUE, FALSE, or UNKNOWN.
expression
Is a column name, a constant, a function, a variable, a scalar subquery, or any combination of
column names, constants, and functions connected by an operator(s) or a subquery. The expression
can also contain the CASE function.
= Is the operator used to test the equality between two expressions.
<> Is the operator used to test the condition of two expressions not being equal to each other.
!= Is the operator used to test the condition of two expressions not being equal to each other.
> Is the operator used to test the condition of one expression being greater than the other.
>= Is the operator used to test the condition of one expression being greater than or equal to the
other expression.
!> Is the operator used to test the condition of one expression not being greater than the other
expression.
< Is the operator used to test the condition of one expression being less than the other.
14
<= Is the operator used to test the condition of one expression being less than or equal to the other
expression.
!< Is the operator used to test the condition of one expression not being less than the other
expression.
string_expression
Is a string of characters and wildcard characters.
[ NOT ] LIKE Indicates that the subsequent character string is to be used with pattern matching.
ESCAPE 'escape_character' Allows a wildcard character to be searched for in a character string
instead of functioning as a wildcard. escape_character is the character that is placed in front of the
wildcard character to denote this special use.
[ NOT ] BETWEEN Specifies an inclusive range of values. Use AND to separate the beginning
and ending values.
IS [ NOT ] NULL Specifies a search for null values, or for values that are not null, depending on
the keywords used. An expression with a bitwise or arithmetic operator evaluates to NULL if any of
the operands is NULL.
CONTAINS Dearches columns containing character-based data for precise or "fuzzy" (less
precise) matches to single words and phrases, the proximity of words within a certain distance of
one another, and weighted matches. Can only be used with SELECT statements.
FREETEXT Provides a simple form of natural language query by searching columns containing
character-based data for values that match the meaning rather than the exact words in the predicate.
Can only be used with SELECT statements.
[ NOT ] IN Specifies the search for an expression, based on the expression's inclusion in or
exclusion from a list. The search expression can be a constant or a column name, and the list can be
a set of constants or, more commonly, a subquery. Enclose the list of values in parentheses.
subquery Can be considered a restricted SELECT statement and is similar to <query_expresssion>
in the SELECT statement. The ORDER BY clause, the COMPUTE clause, and the INTO keyword
are not allowed.
ALL Used with a comparison operator and a subquery. Returns TRUE for <predicate> if all values
retrieved for the subquery satisfy the comparison operation, or FALSE if not all values satisfy the
comparison or if the subquery returns no rows to the outer statement
{ SOME | ANY } Used with a comparison operator and a subquery. Returns TRUE for <predicate>
if any value retrieved for the subquery satisfies the comparison operation, or FALSE if no values in
the subquery satisfy the comparison or if the subquery returns no rows to the outer statement.
Otherwise, the expression is unknown.
EXISTS Used with a subquery to test for the existence of rows returned by the subquery. The
order of precedence for the logical operators is NOT (highest), followed by AND, followed by OR.
The order of evaluation at the same precedence level is from left to right. Parentheses can be used to
override this order in a search condition.
15
ESCAPE simbola lietošana WHERE rindā kopā ar
LIKE operatoru
This example assumes a description column exists in finances table. To search for the rows in
which the description column contains the exact characters g_, use the ESCAPE option because _
is a wildcard character. Without specifying the ESCAPE option, the query would search for any
description values containing the letter g followed by any single character other than the _
character.
SELECT *
FROM Preces
WHERE NOSAUKUMS LIKE 'gs_' ESCAPE 's';
16
UNION Operator
Combines the results of two or more queries into a single result set consisting of all the rows
belonging to all queries in the union. This is different from using joins that combine columns from
two tables. Two basic rules for combining the result sets of two queries with UNION are:
1) The number and the order of the columns must be identical in all queries.
2) The data types must be compatible.
{ < query specification > | ( < query expression > ) }
UNION [ ALL ]
< query specification | ( < query expression > )
[ UNION [ ALL ] < query specification | ( < query expression > )
[ ...n ] ]
< query_specification > | ( < query_expression > )
Is a query specification or query expression that returns data to be combined with the data from
another query specification or query expression. The definitions of the columns that are part of a
UNION operation do not have to be identical, but they must be compatible through implicit
conversion. The table shows the rules for comparing the data types and options of corresponding
(ith) columns.
Data type of ith column
Data type of ith column of results table
Not data type-compatible (data Error returned by SQL Server.
conversion not handled implicitly by
Microsoft® SQL Server™).
Both fixed-length char with lengths L1 Fixed-length char with length equal to the
and L2.
greater of L1 and L2.
Both fixed-length binary with lengths Fixed-length binary with length equal to the
L1 and L2.
greater of L1 and L2.
Either or both variable-length char.
Variable-length char with length equal to the
maximum of the lengths specified for the ith
columns.
Either or both variable-length binary.
Variable-length binary with length equal to
the maximum of the lengths specified for the
ith columns.
Both numeric data types (for example, Data type equal to the maximum precision of
smallint, int, float, money).
the two columns. For example, if the ith
column of table A is of type int and the ith
column of table B is of type float, then the
data type of the ith column of the results table
is float because float is more precise than int.
Both columns' descriptions specify Specifies NOT NULL.
NOT NULL.
UNION Specifies that multiple result sets are to be combined and returned as a single result set.
ALL
Incorporates all rows into the results, including duplicates. If not specified, duplicate rows
are removed.
17
ORDER BY Clause
Specifies the sort for the result set. The ORDER BY clause is invalid in views, inline functions,
derived tables, and subqueries, unless TOP is also specified.
[ ORDER BY { order_by_expression [ ASC | DESC ] }
[ ,...n] ]
order_by_expression
Specifies a column on which to sort. A sort column can be specified as a name or column alias
(which can be qualified by the table or view name), an expression, or a nonnegative integer
representing the position of the name, alias, or expression in select list.
Multiple sort columns can be specified. The sequence of the sort columns in the ORDER BY clause
defines the organization of the sorted result set.
The ORDER BY clause can include items not appearing in the select list. However, if SELECT
DISTINCT is specified, or if the SELECT statement contains a UNION operator, the sort columns
must appear in the select list.
Furthermore, when the SELECT statement includes a UNION operator, the column names or
column aliases must be those specified in the first select list.
Note ntext, text, or image columns cannot be used in an ORDER BY clause.
ASC
Specifies that the values in the specified column should be sorted in ascending order, from lowest
value to highest value.
DESC
Specifies that the values in the specified column should be sorted in descending order, from highest
value to lowest value.
Null values are treated as the lowest possible values.
There is no limit to the number of items in the ORDER BY clause. However, there is a limit of
8,060 bytes for the row size of intermediate worktables needed for sort operations. This limits the
total size of columns specified in an ORDER BY clause.
18
COMPUTE operators
Generates totals that appear as additional summary columns at the end of the
result set. When used with BY, the COMPUTE clause generates control-breaks
and subtotals in the result set. You can specify COMPUTE BY and COMPUTE
in the same query.
COMPUTE AVG | COUNT | MAX | MIN | STDEV | STDEVP | VAR | VARP | SUM
( expression ) [ ,...n ] [ BY expression [ ,...n ] ]
Row aggregate function
Result
AVG
Average of the values in the numeric expression
COUNT
Number of selected rows
MAX
Highest value in the expression
MIN
Lowest value in the expression
STDEV
Statistical standard deviation for all values in the
expression
STDEVP
Statistical standard deviation for the population for all
values in the expression
SUM
Total of the values in the numeric expression
VAR
Statistical variance for all values in the expression
VARP
Statistical variance for the population for all values in
the expression
There is no equivalent to COUNT(*). To find the summary information produced by GROUP BY
and COUNT(*), use a COMPUTE clause without BY. These functions ignore null values.
The DISTINCT keyword is not allowed with row aggregate functions when they are specified with
the COMPUTE clause.
( expression )
An expression, such as the name of a column on which the calculation is performed. expression
must appear in the select list and must be specified exactly the same as one of the expressions in the
select list. A column alias specified in the select list cannot be used within expression.
BY expression
Generates control-breaks and subtotals in the result set. expression is an exact copy of an
order_by_expression in the associated ORDER BY clause. Typically, this is a column name or
column alias. Multiple expressions can be specified. Listing multiple expressions after BY breaks a
group into subgroups and applies the aggregate function at each level of grouping.
If you use COMPUTE BY, you must also use an ORDER BY clause. The expressions must be
identical to or a subset of those listed after ORDER BY, and must be in the same sequence. For
example, if the ORDER BY clause is:
ORDER BY a, b, c
The COMPUTE clause can be any (or all) of these:
COMPUTE BY a, b, c
COMPUTE BY a, b
COMPUTE BY a
19
You cannot use COMPUTE in a SELECT INTO statement because statements including
COMPUTE generate tables and their summary results are not stored in the database. Therefore, any
calculations produced by COMPUTE do not appear in the new table created with the SELECT
INTO statement.
Tabula Darbinieki
UZV DZIM ALGA FIRMA
Celms sieviete
250 AAA
Koks sieviete
200 BBB
Lapa vīrietis
200 AAA
Sakne vīrietis
250 BBB
Zars vīrietis
150 AAA
1. piemērs
SELECT UZV, ALGA
FROM Darbinieki
COMPUTE SUM(ALGA);
2. piemērs ar COMPUTE.
SELECT UZV, ALGA
FROM Darbinieki
COMPUTE SUM(ALGA) BY DZIM
UZV
Koks
Zars
Celms
Sakne
Lapa
ALGA
200
150
250
250
200
Sum
1050
UZV
Koks
Celms
Zars
Sakne
Lapa
ALGA
200
250
sum
450
150
250
200
sum
600
20
FOR Clause
FOR clause is used to specify either the BROWSE or the XML option (BROWSE and XML are
unrelated options).
[ FOR { BROWSE | XML { RAW | AUTO | EXPLICIT }
[ , XMLDATA ]
[ , ELEMENTS ]
[ , BINARY BASE64 ]
}
]
BROWSE
Specifies that updates be allowed while viewing the data in a DB-Library browse mode cursor. A
table can be browsed in an application if the table includes a time-stamped column (defined with the
timestamp data type), the table has a unique index, and the FOR BROWSE option is at the end of
the SELECT statement(s) sent to SQL Server.
Note It is not possible to use the <lock_hint> HOLDLOCK in a SELECT statement that includes
the FOR BROWSE option.
The FOR BROWSE option cannot appear in SELECT statements joined by the UNION operator.
XML
Specifies that the results of a query are to be returned as an XML document. One of these XML
modes must be specified: RAW, AUTO, EXPLICIT.
RAW
Takes the query result and transforms each row in the result set into an XML element with a generic
identifier <row /> as the element tag.
AUTO
Returns query results in a simple, nested XML tree. Each table in the FROM clause, for which at
least one column is listed in the SELECT clause, is represented as an XML element. The columns
listed in the SELECT clause are mapped to the appropriate element attributes.
EXPLICIT
Specifies that the shape of the resulting XML tree is defined explicitly. Using this mode, queries
must be written in a particular way so that additional information about the desired nesting is
specified explicitly.
XMLDATA
Returns the schema, but does not add the root element to the result. If XMLDATA is specified, it is
appended to the document.
ELEMENTS
Specifies that the columns are returned as subelements. Otherwise, they are mapped to XML
attributes.
BINARY BASE64
Specifies that the query returns the binary data in binary base64-encoded format. In retrieving
binary data using RAW and EXPLICIT mode, this option must be specified. This is the default in
AUTO mode.
21
OPTION Clause
Specifies that the indicated query hint should be used throughout the entire query. Each query hint
can be specified only once, although multiple query hints are permitted. Only one OPTION clause
may be specified with the statement. The query hint affects all operators in the statement. If a
UNION is involved in the main query, only the last query involving a UNION operator can have
the OPTION clause. If one or more query hints causes the query optimizer to not generate a valid
plan, error 8622 is produced.
Caution Because the query optimizer usually selects the best execution plan for a query, it is
recommended that <join_hint>, <query_hint>, and <table_hint> be used only as a last resort by
experienced database administrators.
[ OPTION ( < query_hint > [ ,...n ) ]
< query_hint > ::=
{ { HASH | ORDER } GROUP
| { CONCAT | HASH | MERGE } UNION
| { LOOP | MERGE | HASH } JOIN
| FAST number_rows
| FORCE ORDER
| MAXDOP number
| ROBUST PLAN
| KEEP PLAN
| KEEPFIXED PLAN
| EXPAND VIEWS
}
{ HASH | ORDER } GROUP
Specifies that aggregations described in the GROUP BY, DISTINCT, or COMPUTE clause of the
query should use hashing or ordering.
{ MERGE | HASH | CONCAT } UNION
Specifies that all UNION operations are performed by merging, hashing, or concatenating UNION
sets. If more than one UNION hint is specified, the query optimizer selects the least expensive
strategy from those hints specified.
{ LOOP | MERGE | HASH } JOIN
Specifies that all join operations are performed by loop join, merge join, or hash join in the whole
query. If more than one join hint is specified, the optimizer selects the least expensive join strategy
from the allowed ones.
If, in the same query, a join hint is also specified for a specific pair of tables, this join hint takes
precedence in the joining of the two tables although the query hints still must be honored. Thus, the
join hint for the pair of tables may only restrict the selection of allowed join methods in the query
hint.
FAST number_rows
Specifies that the query is optimized for fast retrieval of the first number_rows (a nonnegative
integer). After the first number_rows are returned, the query continues execution and produces its
full result set.
FORCE ORDER
Specifies that the join order indicated by the query syntax is preserved during query optimization.
MAXDOP number
Overrides the max degree of parallelism configuration option (of sp_configure) only for the query
specifying this option. All semantic rules used with max degree of parallelism configuration
option are applicable when using the MAXDOP query hint.
22
ROBUST PLAN
Forces the query optimizer to attempt a plan that works for the maximum potential row size,
possibly at the expense of performance. When the query is processed, intermediate tables and
operators may need to store and process rows that are wider than any of the input rows. The rows
may be so wide that, in some cases, the particular operator cannot process the row. If this happens,
SQL Server produces an error during query execution. By using ROBUST PLAN, you instruct the
query optimizer not to consider any query plans that may encounter this problem.
KEEP PLAN
Forces the query optimizer to relax the estimated recompile threshold for a query. The estimated
recompile threshold is the point at which a query is automatically recompiled when the estimated
number of indexed column changes (update, delete, or insert) have been made to a table. Specifying
KEEP PLAN ensures that a query will not be recompiled as frequently when there are multiple
updates to a table.
KEEPFIXED PLAN
Forces the query optimizer not to recompile a query due to changes in statistics or to the indexed
column (update, delete, or insert). Specifying KEEPFIXED PLAN ensures that a query will be
recompiled only if the schema of the underlying tables is changed or sp_recompile is executed
against those tables.
EXPAND VIEWS
Specifies that the indexed views are expanded and the query optimizer will not consider any
indexed view as a substitute for any part of the query. (A view is expanded when the view name is
replaced by the view definition in the query text.) This query hint virtually disallows direct use of
indexed views and indexes on indexed views in the query plan.
The indexed view is not expanded only if the view is directly referenced in the SELECT part of the
query and WITH (NOEXPAND) or WITH (NOEXPAND, INDEX( index_val [ ,...n ] ) ) is
specified. Only the views in the SELECT portion of statements, including those in INSERT,
UPDATE, and DELETE statements are affected by the hint.
Remarks
The order of the clauses in the SELECT statement is significant. Any of the optional clauses can be
omitted, but when used, they must appear in the appropriate order.
SELECT statements are allowed in user-defined functions only if the select lists of these statements
contain expressions that assign values to variables that are local to the functions.
A table variable, in its scope, may be accessed like a regular table and thus may be used as a table
source in a SELECT statement.
A four-part name constructed with the OPENDATASOURCE function as the server-name part may
be used as a table source in all places a table name can appear in SELECT statements.
Some syntax restrictions apply to SELECT statements involving remote tables. The length returned
for text or ntext columns included in the select list defaults to the smallest of the actual size of the
text, the default TEXTSIZE session setting, or the hard-coded application limit. To change the
length of returned text for the session, use the SET statement. By default, the limit on the length of
text data returned with a SELECT statement is 4,000 bytes.
SQL Server raises exception 511 and rolls back the current executing statement if either of these
occur:

The SELECT statement produces a result row or an intermediate work table row exceeding
8,060 bytes.

The DELETE, INSERT, or UPDATE statement attempts action on a row exceeding 8,060
bytes.
In SQL Server, an error occurs if no column name is given to a column created by a SELECT INTO
or CREATE VIEW statement.
Selecting Identity Columns
When selecting an existing identity column into a new table, the new column inherits the
IDENTITY property, unless one of the following conditions is true:
23




The SELECT statement contains a join, GROUP BY clause, or aggregate function.
Multiple SELECT statements are joined with UNION.
The identity column is listed more than once in the select list.
The identity column is part of an expression.
If any of these conditions is true, the column is created NOT NULL instead of inheriting the
IDENTITY property. All rules and restrictions for the identity columns apply to the new table.
Old-Style Outer Joins
Earlier versions of SQL Server supported the definition of outer joins that used the *= and =*
operators in the WHERE clause. SQL Server version 7.0 supports the SQL-92 standard, which
provides join operators in the FROM clause. It is recommended that queries be rewritten to use the
SQL-92 syntax.
Processing Order of WHERE, GROUP BY, and HAVING Clauses
This list shows the processing order for a SELECT statement with a WHERE clause, a GROUP BY
clause, and a HAVING clause:
1.
The WHERE clause excludes rows not meeting its search condition.
2.
The GROUP BY clause collects the selected rows into one group for each unique value in
the GROUP BY clause.
3.
Aggregate functions specified in the select list calculate summary values for each group.
4.
The HAVING clause further excludes rows not meeting its search condition.
Permissions
SELECT permissions default to members of the sysadmin fixed server role, the db_owner and
db_datareader fixed database roles, and the table owner. Members of the sysadmin, db_owner,
and db_securityadmin roles, and the table owner can transfer permissions to other users.
If the INTO clause is used to create a permanent table, the user must have CREATE TABLE
permission in the destination database.
24
CONTAINS
Is a predicate used to search columns containing character-based data types for precise or fuzzy
(less precise) matches to single words and phrases, the proximity of words within a certain distance
of one another, or weighted matches. CONTAINS can search for:
1) A word or phrase.
2) The prefix of a word or phrase.
3) A word near another word.
4) A word inflectionally generated from another (for example, the word drive is the
inflectional stem of drives, drove, driving, and driven).
5) A word that has a higher designated weighting than another word.
CONTAINS
( { column | * } , '< contains_search_condition >'
)
< contains_search_condition > ::=
{ < simple_term >
| < prefix_term >
| < generation_term >
| < proximity_term >
| < weighted_term >
}
| { ( < contains_search_condition > )
{ AND | AND NOT | OR } < contains_search_condition > [ ...n ]
}
< simple_term > ::=
word | " phrase "
< prefix term > ::=
{ "word * " | "phrase * " }
< generation_term > ::=
FORMSOF ( INFLECTIONAL , < simple_term > [ ,...n ] )
< proximity_term > ::=
{ < simple_term > | < prefix_term > }
{ { NEAR | ~ } { < simple_term > | < prefix_term > } } [ ...n ]
< weighted_term > ::=
ISABOUT
({{
< simple_term >
| < prefix_term >
| < generation_term >
| < proximity_term >
}
[ WEIGHT ( weight_value ) ]
} [ ,...n ]
)
column
Is the name of a specific column that has been registered for full-text searching. Columns of the
character string data types are valid full-text searching columns.
25
*
Specifies that all columns in the table registered for full-text searching should be used to search for
the given contains search condition(s). If more than one table is in the FROM clause, * must be
qualified by the table name.
<contains_search_condition>
Specifies some text to search for in column. Variables cannot be used for the search condition.
word
Is a string of characters without spaces or punctuation.
phrase
Is one or more words with spaces between each word.
Note Some languages, such as those in Asia, can have phrases that consist of one or more words
without spaces between them.
<simple_term>
Specifies a match for an exact word (one or more characters without spaces or punctuation in
single-byte languages) or a phrase (one or more consecutive words separated by spaces and optional
punctuation in single-byte languages). Examples of valid simple terms are "blue berry", blueberry,
and "Microsoft SQL Server". Phrases should be enclosed in double quotation marks (""). Words in
a phrase must appear in the same order as specified in <contains_search_condition> as they appear
in the database column. The search for characters in the word or phrase is case insensitive. Noise
words (such as a, and, or the) in full-text indexed columns are not stored in the full-text index. If a
noise word is used in a single word search, SQL Server returns an error message indicating that
only noise words are present in the query. SQL Server includes a standard list of noise words in the
directory \Mssql\Ftdata\Sqlserver\Config.
Punctuation is ignored. Therefore, CONTAINS(testing, "computer failure") matches a row with the
value, "Where is my computer? Failure to find it would be expensive."
<prefix_term>
Specifies a match of words or phrases beginning with the specified text. Enclose a prefix term in
double quotation marks ("") and add an asterisk (*) before the ending quotation mark, so that all
text starting with the simple term specified before the asterisk is matched. The clause should be
specified this way: CONTAINS (column, '"text*"') The asterisk matches zero, one, or more
characters (of the root word or words in the word or phrase). If the text and asterisk are not
delimited by double quotation marks, as in CONTAINS (column, 'text*'), full-text search
considers the asterisk as a character and will search for exact matches to text*.
When <prefix_term> is a phrase, each word contained in the phrase is considered to be a separate
prefix. Therefore, a query specifying a prefix term of "local wine *" matches any rows with the text
of "local winery", "locally wined and dined", and so on.
<generation_term>
Specifies a match of words when the included simple terms include variants of the original word for
which to search.
INFLECTIONAL
Specifies that the plural and singular, as well as the gender and neutral forms of nouns, verbs, and
adjectives should be matched. The various tenses of verbs should be matched too.
A given <simple_term> within a <generation_term> will not match both nouns and verbs.
<proximity_term>
Specifies a match of words or phrases that must be close to one another. <proximity_term> operates
similarly to the AND operator: both require that more than one word or phrase exist in the column
being searched. As the words in <proximity_term> appear closer together, the better the match.
NEAR | ~
Indicates that the word or phrase on the left side of the NEAR or ~ operator should be
approximately close to the word or phrase on the right side of the NEAR or ~ operator. Multiple
proximity terms can be chained, for example:
a NEAR b NEAR c
26
This means that word or phrase a should be near word or phrase b, which should be near word or
phrase c.
Microsoft® SQL Server™ ranks the distance between the left and right word or phrase. A low rank
value (for example, 0) indicates a large distance between the two. If the specified words or phrases
are far apart from each other, the query is considered to be satisfied; however, the query has a very
low (0) rank value. However, if <contains_search_condition> consists of only one or more NEAR
proximity terms, SQL Server does not return rows with a rank value of 0.
<weighted_term>
Specifies that the matching rows (returned by the query) match a list of words and phrases, each
optionally given a weighting value.
ISABOUT
Specifies the <weighted_term> keyword.
WEIGHT (weight_value)
Specifies a weight value which is a number from 0.0 through 1.0. Each component in
<weighted_term> may include a weight_value. weight_value is a way to change how various
portions of a query affect the rank value assigned to each row matching the query. Weighting forces
a different measurement of the ranking of a value because all the components of <weighted_term>
are used together to determine the match. A row is returned if there is a match on any one of the
ISABOUT parameters, whether or not a weight value is assigned
AND | AND NOT | OR
Specifies a logical operation between two contains search conditions. When
<contains_search_condition> contains parenthesized groups, these parenthesized groups are
evaluated first. After evaluating parenthesized groups, these rules apply when using these logical
operators with contains search conditions:

NOT is applied before AND.

NOT can only occur after AND, as in AND NOT. The OR NOT operator is not allowed.
NOT cannot be specified before the first term (for example, CONTAINS (mycolumn, 'NOT
"phrase_to_search_for" ' ).

AND is applied before OR.

Boolean operators of the same type (AND, OR) are associative and can therefore be applied
in any order.
n
Is a placeholder indicating that multiple contains search conditions and terms within them can be
specified.
CONTAINS is not recognized as a keyword if the compatibility level is less than 70.
27
Operatora CONTAINS lietošanas piemēri
SELECT NOSAUKUMS
FROM Produkti
WHERE CENA = 15.00 AND CONTAINS(IEPAKOJUMS, 'pudele');
B. Use CONTAINS and phrase in <simple_term>
This example returns all products that contain either the phrase "sasquatch ale"
or "steeleye stout."
SELECT NOSAUKUMS, DAUDZUMS
FROM Produkti
WHERE CONTAINS(NOSAUKUMS,' "piens"OR "sviests" ');
SELECT NOSAUKUMS
FROM Produkti
WHERE CONTAINS(NOSAUKUMS, ' "ziv*" ');
SELECT NOSAUKUMS
FROM Preces
WHERE CONTAINS(NOSAUKUMS, '"jūras*" OR "upes*"')
E. Use CONTAINS with <proximity_term>
This example returns all product names that have the word "Boysenberry" near
the word "spread."
SELECT ProductName
FROM Products
WHERE CONTAINS(ProductName, 'spread NEAR Boysenberry')
F. Use CONTAINS with <generation_term>
This example searches for all products with words of the form dry: dried,
drying, and so on.
SELECT ProductName
FROM Products
WHERE CONTAINS(ProductName, ' FORMSOF (INFLECTIONAL, dry) ')
G. Use CONTAINS with <weighted_term>
This example searches for all product names containing the words spread,
sauces, or relishes, and different weightings are given to each word.
SELECT CategoryName, Description
FROM Categories
28
WHERE CONTAINS(Description, 'ISABOUT (spread weight (.8),
sauces weight (.4), relishes weight (.2) )' )
H. Use CONTAINS with variables
This example uses a variable instead of a specific search term.
DECLARE @SearchWord varchar(30)
SET @SearchWord ='Moon'
SELECT
pr_info FROM pub_info
@SearchWord)
WHERE
CONTAINS(pr_info,
29
CONTAINSTABLE
Returns a table of zero, one, or more rows for those columns containing character-based data types
for precise or fuzzy (less precise) matches to single words and phrases, the proximity of words
within a certain distance of one another, or weighted matches. CONTAINSTABLE can be
referenced in the FROM clause of a SELECT statement as if it were a regular table name.
Queries using CONTAINSTABLE specify contains-type full-text queries that return a relevance
ranking value (RANK) for each row. The CONTAINSTABLE function uses the same search
conditions as the CONTAINS predicate.
CONTAINSTABLE ( table , { column | * } , ' < contains_search_condition > '
[ , top_n_by_rank ] )
< contains_search_condition > ::=
{ < simple_term >
| < prefix_term >
| < generation_term >
| < proximity_term >
| < weighted_term >
}
| { ( < contains_search_condition > )
{ AND | AND NOT | OR } < contains_search_condition > [ ...n ]
}
< simple_term > ::=
word | " phrase "
< prefix term > ::=
{ "word * " | "phrase * " }
< generation_term > ::=
FORMSOF ( INFLECTIONAL , < simple_term > [ ,...n ] )
< proximity_term > ::=
{ < simple_term > | < prefix_term > }
{ { NEAR | ~ } { < simple_term > | < prefix_term > } } [ ...n ]
< weighted_term > ::=
ISABOUT
({{
< simple_term >
| < prefix_term >
| < generation_term >
| < proximity_term >
}
[ WEIGHT ( weight_value ) ]
} [ ,...n ]
)
Arguments
table
Is the name of the table that has been marked for full-text querying. table can be a one-, two-, or
three-part database object name. table cannot specify a server name and cannot be used in queries
against linked servers.
column
Is the name of the column to search, which resides in table. Columns of the character string data
types are valid full-text searching columns.
*
30
Specifies that all columns in the table that have been registered for full-text searching should be
used to search for the given contains search condition(s).
top_n_by_rank
Specifies that only the n highest ranked matches, in descending order, are returned. Applies only
when an integer value, n, is specified.
<contains_search_condition>
Specifies some text to search for in column. Variables cannot be used for the search condition. For
more information, see CONTAINS.
Remarks
The table returned has a column named KEY that contains full-text key values. Each full-text
indexed table has a column whose values are guaranteed to be unique, and the values returned in the
KEY column are the full-text key values of the rows that match the selection criteria specified in
the contains search condition. The TableFulltextKeyColumn property, obtained from the
OBJECTPROPERTY function, provides the identity for this unique key column. To obtain the rows
you want from the original table, specify a join with the CONTAINSTABLE rows. The typical
form of the FROM clause for a SELECT statement using CONTAINSTABLE is:
SELECT select_list
FROM table AS FT_TBL INNER JOIN
CONTAINSTABLE(table, column, contains_search_condition) AS KEY_TBL
ON FT_TBL.unique_key_column = KEY_TBL.[KEY]
The table produced by CONTAINSTABLE includes a column named RANK. The RANK column
is a value (from 0 through 1000) for each row indicating how well a row matched the selection
criteria. This rank value is typically used in one of these ways in the SELECT statement:

In the ORDER BY clause to return the highest-ranking rows as the first rows in the table.

In the select list to see the rank value assigned to each row.

In the WHERE clause to filter out rows with low rank values.
CONTAINSTABLE is not recognized as a keyword if the compatibility level is less than 70. For
more information, see sp_dbcmptlevel.
Permissions
Execute permissions are available only by users with the appropriate SELECT privileges on the
table or the referenced table's columns.
Examples
A. Return rank values using CONTAINSTABLE
This example searches for all product names containing the words breads, fish, or beers, and
different weightings are given to each word. For each returned row matching this search criteria, the
relative closeness (ranking value) of the match is shown. In addition, the highest ranking rows are
returned first.
USE Northwind
GO
SELECT FT_TBL.CategoryName, FT_TBL.Description, KEY_TBL.RANK
FROM Categories AS FT_TBL INNER JOIN
CONTAINSTABLE(Categories, Description,
'ISABOUT (breads weight (.8),
fish weight (.4), beers weight (.2) )' ) AS KEY_TBL
ON FT_TBL.CategoryID = KEY_TBL.[KEY]
ORDER BY KEY_TBL.RANK DESC
GO
B. Return rank values greater than specified value using CONTAINSTABLE
This example returns the description and category name of all food categories for which the
Description column contains the words "sweet and savory" near either the word "sauces" or the
word "candies." All rows with a category name "Seafood" are disregarded. Only rows with a rank
value of 2 or higher are returned.
USE Northwind
GO
SELECT FT_TBL.Description,
FT_TBL.CategoryName,
31
KEY_TBL.RANK
FROM Categories AS FT_TBL INNER JOIN
CONTAINSTABLE (Categories, Description,
'("sweet and savory" NEAR sauces) OR
("sweet and savory" NEAR candies)'
) AS KEY_TBL
ON FT_TBL.CategoryID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
AND FT_TBL.CategoryName <> 'Seafood'
ORDER BY KEY_TBL.RANK DESC
C. Return top 10 ranked results using CONTAINSTABLE and Top_n_by_rank
This example returns the description and category name of the top 10 food categories where the
Description column contains the words "sweet and savory" near either the word "sauces" or the
word "candies."
SELECT FT_TBL.Description,
FT_TBL.CategoryName,
KEY_TBL.RANK
FROM Categories AS FT_TBL INNER JOIN
CONTAINSTABLE (Categories, Description,
'("sweet and savory" NEAR sauces) OR
("sweet and savory" NEAR candies)'
, 10
) AS KEY_TBL
ON FT_TBL.CategoryID = KEY_TBL.[KEY]
32
Expressions
A combination of symbols and operators that Microsoft® SQL Server™ evaluates to obtain a single
data value. Simple expressions can be a single constant, variable, column, or scalar function.
Operators can be used to join two or more simple expressions into a complex expression.
{ constant
| scalar_function
| [ alias. ] column
| local_variable
| ( expression )
| ( scalar_subquery )
| { unary_operator } expression
| expression { binary_operator } expression
}
constant
Is a symbol that represents a single, specific data value. constant is one or more alphanumeric
characters (letters a-z, A-Z, and numbers 0-9) or symbols (exclamation point (!), at sign (@),
number sign (#), and so on). Character and datetime values are enclosed in quotation marks, while
binary strings and numeric constants are not. For more information, see Constants.
scalar_function
Is a unit of Transact-SQL syntax that provides a specific service and returns a single value.
scalar_function can be built-in scalar functions, such as the SUM, GETDATE, or CAST functions,
or scalar user-defined functions.
[alias.]
Is the alias, or correlation name, assigned to a table by the AS keyword in the FROM clause.
column
Is the name of a column. Only the name of the column is allowed in an expression; a four-part name
cannot be specified.
local_variable
Is the name of a user-defined variable. For more information, see DECLARE @local_variable.
(expression)
Is any valid SQL Server expression as defined in this topic. The parentheses are grouping operators
that ensure that all the operators in the expression within the parentheses are evaluated before the
resulting expression is combined with another.
(scalar_subquery)
Is a subquery that returns one value.
{unary_operator}
Is an operator that has only one numeric operand:
1) + indicates a positive number.
2) - indicates a negative number.
3) ~ indicates the one's complement operator.
Unary operators can be applied only to expressions that evaluate to any of the data types of the
numeric data type category.
{binary_operator}
Is an operator that defines the way two expressions are combined to yield a single result. binary
_operator can be an arithmetic operator, the assignment operator (=), a bitwise operator, a
comparison operator, a logical operator, the string concatenation operator (+), or a unary operator.
33
For a simple expression built of a single constant, variable, scalar function, or column name, the
data type, collation, precision, scale, and value of the expression is the data type, collation,
precision, scale, and value of the referenced element.
When two expressions are combined using comparison or logical operators, the resulting data type
is Boolean and the value is one of three values: TRUE, FALSE, or UNKNOWN. When two
expressions are combined using arithmetic, bitwise, or string operators, the operator determines the
resulting data type.
Complex expressions made up of many symbols and operators evaluate to a single-valued result.
The data type, collation, precision, and value of the resulting expression is determined by
combining the component expressions, two at a time, until a final result is reached. The sequence in
which the expressions are combined is defined by the precedence of the operators in the expression.
Remarks
Two expressions can be combined by an operator if they both have data types supported by the
operator and at least one of these conditions is TRUE:
1) The expressions have the same data type.
2) The data type with the lower precedence can be implicitly converted to the data type with
the higher data type precedence.
3) The CAST function can explicitly convert the data type with the lower precedence to either
the data type with the higher precedence or to an intermediate data type that can be
implicitly converted to the data type with the higher precedence.
If there is no supported implicit or explicit conversion, the two expressions cannot be combined.
The collation of any expression that evaluates to a character string is set following the rules of
collation precedence.
Loģikas funkcijas CASE lietošana
SELECT Valsts_nosaukums = CASE Tabula_1.VALSTS
WHEN ‘LAT’ THEN ‘Latvija’
WHEN ‘LIE’ THEN ‘Lietuva’
WHEN ‘IGA’ THEN ‘Igaunija’
ELSE ‘Nav zināma’
END, Tabula_1.GADS, …
SELECT Daudzums = CASE WHEN GADS = 2000 THEN 20 000
WHEN GADS = 2001 THEN 40 000
ELSE 0
END, …
Funkcijas ISNULL lietošana
SELECT Samaksa = ISNULL(TABULA_1.ALGA, 0), …
34
Join Fundamentals
By using joins, you can retrieve data from two or more tables based on logical relationships
between the tables. Joins indicate how Microsoft® SQL Server™ 2000 should use data from one
table to select the rows in another table.
A join condition defines the way two tables are related in a query by:

Specifying the column from each table to be used for the join. A typical join condition
specifies a foreign key from one table and its associated key in the other table.

Specifying a logical operator (=, <>, and so on) to be used in comparing values from the
columns.
Joins can be specified in either the FROM or WHERE clauses. The join conditions combine with
the WHERE and HAVING search conditions to control the rows that are selected from the base
tables referenced in the FROM clause.
Specifying the join conditions in the FROM clause helps separate them from any other search
conditions that may be specified in a WHERE clause, and is the recommended method for
specifying joins. A simplified SQL-92 FROM clause join syntax is:
FROM first_table join_type second_table [ON (join_condition)]
join_type specifies what kind of join is performed: an inner, outer, or cross join. join_condition
defines the predicate to be evaluated for each pair of joined rows. This is an example of a FROM
clause join specification:
FROM Suppliers JOIN Products
ON (Suppliers.SupplierID = Products.SupplierID)
This is a simple SELECT statement using this join:
SELECT ProductID,
Suppliers.SupplierID,
CompanyName
FROM Suppliers JOIN Products
ON (Suppliers.SupplierID = Products.SupplierID)
WHERE UnitPrice > $10
AND CompanyName LIKE N'F%'
GO
The select returns the product and supplier information for any combination of parts supplied by a
company for which the company name starts with the letter F and the price of the product is more
than $10.
When multiple tables are referenced in a single query, all column references must be unambiguous.
In the previous example, both the Products and Suppliers table have a column named SupplierID.
Any column name that is duplicated between two or more tables referenced in the query must be
qualified with the table name. All references to the SupplierID columns in the example are
qualified.
35
When a column name is not duplicated in two or more tables used in the query, references to it do
not have to be qualified with the table name. This is shown in the previous example. Such a
SELECT statement is sometimes difficult to understand because there is nothing to indicate the
table that provided each column. The readability of the query is improved if all columns are
qualified with their table names. The readability is further improved if table aliases are used,
especially when the table names themselves must be qualified with the database and owner names.
This is the same example, except that table aliases have been assigned and the columns qualified
with table aliases to improve readability:
SELECT P.ProductID,
S.SupplierID,
S.CompanyName
FROM Suppliers AS S JOIN Products AS P
ON (S.SupplierID = P.SupplierID)
WHERE P.UnitPrice > $10
AND S.CompanyName LIKE N'F%'
The previous examples specified the join conditions in the FROM clause, which is the preferred
method. This query contains the same join condition specified in the WHERE clause:
SELECT P.ProductID,
S.SupplierID,
S.CompanyName
FROM Suppliers AS S, Products AS P
WHERE S.SupplierID = P.SupplierID
AND P.UnitPrice > $10
AND S.CompanyName LIKE N'F%'
The select list for a join can reference all the columns in the joined tables, or any subset of the
columns. The select list is not required to contain columns from every table in the join. For
example, in a three-table join, only one table can be used to bridge from one of the other tables to
the third table, and none of the columns from the middle table have to be referenced in the select
list.
Although join conditions usually have equality comparisons (=), other comparison or relational
operators can be specified, as can other predicates. For more information, see Using Operators in
Expressions and WHERE.
When SQL Server processes joins, the query engine chooses the most efficient method (out of
several possibilities) of processing the join. Although the physical execution of various joins uses
many different optimizations, the logical sequence is:

The join conditions in the FROM clause are applied.

The join conditions and search conditions from the WHERE clause are applied.

The search conditions from the HAVING clause are applied.
This sequence can sometimes influence the results of the query if conditions are moved between the
FROM and WHERE clauses.
Columns used in a join condition are not required to have the same name or be the same data type.
However, if the data types are not identical, they must be compatible, or be types that SQL Server
can implicitly convert. If the data types cannot be implicitly converted, the join condition must
36
explicitly convert the data type using the CAST function. For more information about implicit and
explicit conversions, see Data Type Conversion.
Most queries using a join can be rewritten using a subquery (a query nested within another query),
and most subqueries can be rewritten as joins. For more information about subqueries, see
Subquery Fundamentals.
Note Tables cannot be joined directly on ntext, text, or image columns. However, tables can
be joined indirectly on ntext, text, or image columns by using SUBSTRING. For example,
SELECT * FROM t1 JOIN t2 ON SUBSTRING(t1.textcolumn, 1, 20) =
SUBSTRING(t2.textcolumn, 1, 20) performs a two-table inner join on the first 20 characters of
each text column in tables t1 and t2. In addition, another possibility for comparing ntext or text
columns from two tables is to compare the lengths of the columns with a WHERE clause, for
example (where a self-join is performed on the pub_info table):
WHERE DATALENGTH(p1.pr_info) = DATALENGTH(p2.pr_info)
37
Subquery Fundamentals
A subquery is a SELECT query that returns a single value and is nested inside a SELECT, INSERT,
UPDATE, or DELETE statement, or inside another subquery. A subquery can be used anywhere an
expression is allowed. In this example a subquery is used as a column expression named
MaxUnitPrice in a SELECT statement.
SELECT Ord.OrderID, Ord.OrderDate,
(SELECT MAX(OrdDet.UnitPrice)
FROM Northwind.dbo.[Order Details] AS OrdDet
WHERE Ord.OrderID = OrdDet.OrderID) AS MaxUnitPrice
FROM Northwind.dbo.Orders AS Ord
A subquery is also called an inner query or inner select, while the statement containing a subquery
is also called an outer query or outer select.
Many Transact-SQL statements that include subqueries can be alternatively formulated as joins.
Other questions can be posed only with subqueries. In Transact-SQL, there is usually no
performance difference between a statement that includes a subquery and a semantically equivalent
version that does not. However, in some cases where existence must be checked, a join yields better
performance. Otherwise, the nested query must be processed for each result of the outer query to
ensure elimination of duplicates. In such cases, a join approach would yield better results. This is an
example showing both a subquery SELECT and a join SELECT that return the same result set:
/* SELECT statement built using a subquery. */
SELECT ProductName
FROM Northwind.dbo.Products
WHERE UnitPrice =
(SELECT UnitPrice
FROM Northwind.dbo.Products
WHERE ProductName = 'Sir Rodney''s Scones')
/* SELECT statement built using a join that returns
the same result set. */
SELECT Prd1.ProductName
FROM Northwind.dbo.Products AS Prd1
JOIN Northwind.dbo.Products AS Prd2
ON (Prd1.UnitPrice = Prd2.UnitPrice)
WHERE Prd2.ProductName = 'Sir Rodney''s Scones'
A subquery nested in the outer SELECT statement has the following components:

A regular SELECT query including the regular select list components.

A regular FROM clause including one or more table or view names.

An optional WHERE clause.

An optional GROUP BY clause.

An optional HAVING clause.
38
The SELECT query of a subquery is always enclosed in parentheses. It cannot include a
COMPUTE or FOR BROWSE clause, and may only include an ORDER BY clause when a TOP
clause is also specified.
A subquery can be nested inside the WHERE or HAVING clause of an outer SELECT, INSERT,
UPDATE, or DELETE statement, or inside another subquery. Up to 32 levels of nesting is possible,
although the limit varies based on available memory and the complexity of other expressions in the
query. Individual queries may not support nesting up to 32 levels. A subquery can appear anywhere
an expression can be used, if it returns a single value.
If a table appears only in a subquery and not in the outer query, then columns from that table cannot
be included in the output (the select list of the outer query).
Statements that include a subquery usually take one of these formats:

WHERE expression [NOT] IN (subquery)

WHERE expression comparison_operator [ANY | ALL] (subquery)

WHERE [NOT] EXISTS (subquery)
In some Transact-SQL statements, the subquery can be evaluated as if it were an independent
query. Conceptually, the subquery results are substituted into the outer query (although this is not
necessarily how Microsoft® SQL Server™ actually processes Transact-SQL statements with
subqueries).
There are three basic types of subqueries. Those that:

Operate on lists introduced with IN, or those that a comparison operator modified by ANY
or ALL.

Are introduced with an unmodified comparison operator and must return a single value.

Are existence tests introduced with EXISTS.
39
Using Variables and Parameters
Transact-SQL has several ways to pass data between Transact-SQL statements. Among these are:

Transact-SQL local variables.
A Transact-SQL variable is an object in Transact-SQL batches and scripts that can hold a
data value. After the variable has been declared, or defined, one Transact-SQL statement in
a batch can set the variable to a value and a later statement in the batch can get the value
from the variable. For example:
DECLARE @EmpIDVar INT
SET @EmpIDVar = 1234
SELECT *
FROM Employees
WHERE EmployeeID = @EmpIDVar

Transact-SQL parameters.
A parameter is an object used to pass data between a stored procedure and the batch or script
that executes the stored procedure. Parameters can be either input or output parameters. For
example:
CREATE PROCEDURE ParmSample @EmpIDParm INT AS
SELECT *
FROM Employees
WHERE EmployeeID = @EmpIDParm
GO
EXEC ParmSample @EmpIDParm = 1234
GO
Applications use application variables and parameter markers to work with the data from TransactSQL statements.

Application variables
The application programming languages such as C, C++, Basic, and Java have their own
variables for holding data. Applications using the database APIs must move the data
returned by Transact-SQL statements into application variables before they can work with
the data. This is typically done using a process called binding. The application uses an API
function to bind the result set column to a program variable. When a row is fetched the API
provider or driver moves the data from the column to the bound program variable.

Parameter markers
Parameter markers are supported by the ADO, OLE DB, and ODBC-based database APIs.
A parameter marker is a question mark (?) placed in the location of an input expression in a
Transact-SQL statement. The parameter marker is then bound to an application variable.
This allows data from application variables to be used as input in Transact-SQL statements.
Parameter markers also let stored procedure output parameters and return codes be bound to
40
application variables. The output data is then returned to the bound variables when the
procedure is executed. The DB-Library API also supports binding stored procedure
parameter and return codes to program variables.
41
SELECT Examples
A. Use SELECT to retrieve rows and columns
This example shows three code examples. This first code example returns all rows (no WHERE
clause is specified) and all columns (using the *) from the authors table in the pubs database.
USE pubs
SELECT *
FROM authors
ORDER BY au_lname ASC, au_fname ASC
-- Alternate way.
USE pubs
SELECT authors.*
FROM customers
ORDER BY au_lname ASC, au_fname ASC
This example returns all rows (no WHERE clause is specified), and only a subset of the columns
(au_lname, au_fname, phone, city, state) from the authors table in the pubs database. In
addition, column headings are added.
USE pubs
SELECT au_fname, au_lname, phone AS Telephone, city, state
FROM authors
ORDER BY au_lname ASC, au_fname ASC
This example returns only the rows for authors who live in California and do not have the last name
McBadden.
USE pubs
SELECT au_fname, au_lname, phone AS Telephone
FROM authors
WHERE state = 'CA' and au_lname <> 'McBadden'
ORDER BY au_lname ASC, au_fname ASC
B. Use SELECT with column headings and calculations
These examples return all rows from titles. The first example returns total year-to-date sales and the
amounts due to each author and publisher. In the second example, the total revenue is calculated for
each book.
USE pubs
SELECT ytd_sales AS Sales,
authors.au_fname + ' '+ authors.au_lname AS Author,
ToAuthor = (ytd_sales * royalty) / 100,
ToPublisher = ytd_sales - (ytd_sales * royalty) / 100
FROM titles INNER JOIN titleauthor
ON titles.title_id = titleauthor.title_id INNER JOIN authors
ON titleauthor.au_id = authors.au_id
ORDER BY Sales DESC, Author ASC
Here is the result set:
Sales
Author
ToAuthor
ToPublisher
----------- ------------------------- ----------- -----------
42
22246
22246
18722
15096
8780
4095
4095
4095
4095
4095
4095
4095
4095
4072
3876
3876
3336
2045
2045
2032
375
375
375
111
NULL
Anne Ringer
Michel DeFrance
Marjorie Green
Reginald Blotchet-Halls
Cheryl Carson
Abraham Bennet
Akiko Yokomoto
Ann Dull
Burt Gringlesby
Dean Straight
Marjorie Green
Michael O'Leary
Sheryl Hunter
Johnson White
Michael O'Leary
Stearns MacFeather
Charlene Locksley
Albert Ringer
Anne Ringer
Innes del Castillo
Livia Karsen
Stearns MacFeather
Sylvia Panteley
Albert Ringer
Charlene Locksley
5339
5339
4493
2113
1404
409
409
409
409
409
409
409
409
407
387
387
333
245
245
243
37
37
37
11
NULL
16907
16907
14229
12983
7376
3686
3686
3686
3686
3686
3686
3686
3686
3665
3489
3489
3003
1800
1800
1789
338
338
338
100
NULL
(25 row(s) affected)
This is the query that calculates the revenue for each book:
USE pubs
SELECT 'Total income is', price * ytd_sales AS Revenue,
'for', title_id AS Book#
FROM titles
ORDER BY Book# ASC
Here is the result set:
Revenue
--------------Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
Total income is
--------------------81859.0500
46318.2000
55978.7800
81859.0500
40619.6800
66515.5400
NULL
201501.0000
81900.0000
NULL
8096.2500
22392.7500
777.0000
81399.2800
26654.6400
7856.2500
180397.2000
61384.0500
(18 row(s) affected)
---for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
Book#
-----BU1032
BU1111
BU2075
BU7832
MC2222
MC3021
MC3026
PC1035
PC8888
PC9999
PS1372
PS2091
PS2106
PS3333
PS7777
TC3218
TC4203
TC7777
43
C. Use DISTINCT with SELECT
This example uses DISTINCT to prevent the retrieval of duplicate author ID numbers.
USE pubs
SELECT DISTINCT au_id
FROM authors
ORDER BY au_id
D. Create tables with SELECT INTO
This first example creates a temporary table named #coffeetabletitles in tempdb. To use this table,
always refer to it with the exact name shown, including the number sign (#).
USE pubs
DROP TABLE #coffeetabletitles
GO
SET NOCOUNT ON
SELECT * INTO #coffeetabletitles
FROM titles
WHERE price < $20
SET NOCOUNT OFF
SELECT name
FROM tempdb..sysobjects
WHERE name LIKE '#c%'
Here is the result set:
name
-----------------------------------------------------------------------#coffeetabletitles______________________________________________________________
____________________________________000000000028
(1 row(s) affected)
CHECKPOINTing database that was changed.
(12 row(s) affected)
name
-----------------------------------------------------------------------newtitles
(1 row(s) affected)
CHECKPOINTing database that was changed.
This second example creates a permanent table named newtitles.
USE pubs
IF EXISTS (SELECT table_name FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = 'newtitles')
DROP TABLE newtitles
GO
EXEC sp_dboption 'pubs', 'select into/bulkcopy', 'true'
USE pubs
SELECT * INTO newtitles
FROM titles
WHERE price > $25 OR price < $20
SELECT name FROM sysobjects WHERE name LIKE 'new%'
44
USE master
EXEC sp_dboption 'pubs', 'select into/bulkcopy', 'false'
Here is the result set:
name
-----------------------------newtitles
(1 row(s) affected)
E. Use correlated subqueries
This example shows queries that are semantically equivalent and illustrates the difference between
using the EXISTS keyword and the IN keyword. Both are examples of a valid subquery retrieving
one instance of each publisher name for which the book title is a business book, and the publisher
ID numbers match between the titles and publishers tables.
USE pubs
SELECT DISTINCT pub_name
FROM publishers
WHERE EXISTS
(SELECT *
FROM titles
WHERE pub_id = publishers.pub_id
AND type = 'business')
-- Or
USE pubs
SELECT distinct pub_name
FROM publishers
WHERE pub_id IN
(SELECT pub_id
FROM titles
WHERE type = 'business')
This example uses IN in a correlated (or repeating) subquery, which is a query that depends on the
outer query for its values. It is executed repeatedly, once for each row that may be selected by the
outer query. This query retrieves one instance of each author's first and last name for which the
royalty percentage in the titleauthor table is 100 and for which the author identification numbers
match in the authors and titleauthor tables.
USE pubs
SELECT DISTINCT au_lname, au_fname
FROM authors
WHERE 100 IN
(SELECT royaltyper
FROM titleauthor
WHERE titleauthor.au_id = authors.au_id)
The above subquery in this statement cannot be evaluated independently of the outer query. It needs
a value for authors.au_id, but this value changes as Microsoft® SQL Server™ examines different
rows in authors.
A correlated subquery can also be used in the HAVING clause of an outer query. This example
finds the types of books for which the maximum advance is more than twice the average for the
group.
45
USE pubs
SELECT t1.type
FROM titles t1
GROUP BY t1.type
HAVING MAX(t1.advance) >= ALL
(SELECT 2 * AVG(t2.advance)
FROM titles t2
WHERE t1.type = t2.type)
This example uses two correlated subqueries to find the names of authors who have participated in
writing at least one popular computing book.
USE pubs
SELECT au_lname, au_fname
FROM authors
WHERE au_id IN
(SELECT au_id
FROM titleauthor
WHERE title_id IN
(SELECT title_id
FROM titles
WHERE type = 'popular_comp'))
F. Use GROUP BY
This example finds the total year-to-date sales of each publisher in the database.
USE pubs
SELECT pub_id, SUM(ytd_sales) AS total
FROM titles
GROUP BY pub_id
ORDER BY pub_id
Here is the result set:
pub_id
-----0736
0877
1389
total
----28286
44219
24941
(3 row(s) affected)
Because of the GROUP BY clause, only one row containing the sum of all sales is returned for each
publisher.
G. Use GROUP BY with multiple groups
This example finds the average price and the sum of year-to-date sales, grouped by type and
publisher ID.
USE pubs
SELECT type, pub_id, AVG(price) AS 'avg', sum(ytd_sales) AS 'sum'
FROM titles
GROUP BY type, pub_id
ORDER BY type, pub_id
Here is the result set:
46
type
-----------business
business
mod_cook
popular_comp
psychology
psychology
trad_cook
UNDECIDED
pub_id
-----0736
1389
0877
1389
0736
0877
0877
0877
avg
--------------------2.9900
17.3100
11.4900
21.4750
11.4825
21.5900
15.9633
NULL
sum
----------18722
12066
24278
12875
9564
375
19566
NULL
(8 row(s) affected)
Warning, null value eliminated from aggregate.
H. Use GROUP BY and WHERE
This example puts the results into groups after retrieving only the rows with advances greater than
$5,000.
USE pubs
SELECT type, AVG(price)
FROM titles
WHERE advance > $5000
GROUP BY type
ORDER BY type
Here is the result set:
type
-----------business
mod_cook
popular_comp
psychology
trad_cook
-------------------------2.99
2.99
21.48
14.30
17.97
(5 row(s) affected)
I. Use GROUP BY with an expression
This example groups by an expression. You can group by an expression if the expression does not
include aggregate functions.
USE pubs
SELECT AVG(ytd_sales), ytd_sales * royalty
FROM titles
GROUP BY ytd_sales * royalty
ORDER BY ytd_sales * royalty
Here is the result set:
----------NULL
111
375
2032
2045
3336
----------NULL
1110
3750
24384
24540
33360
47
3876
4072
4095
8780
15096
18722
22246
38760
40720
40950
140480
211344
449328
533904
(13 row(s) affected)
J. Compare GROUP BY and GROUP BY ALL
The first example produces groups only for those books that commanded royalties of 10 percent.
Because no modern cookbooks have a royalty of 10 percent, there is no group in the results for the
mod_cook type.
The second example produces groups for all types, including modern cookbooks and
UNDECIDED, although the modern cookbook group does not include any rows that meet the
qualification specified in the WHERE clause.
The column that holds the aggregate value (the average price) is NULL for groups that lack
qualifying rows.
USE pubs
SELECT type, AVG(price)
FROM titles
WHERE royalty = 10
GROUP BY type
ORDER BY type
Here is the result set:
type
-----------business
popular_comp
psychology
trad_cook
-------------------------17.31
20.00
14.14
17.97
(4 row(s) affected)
-- Using GROUP BY ALL
USE pubs
SELECT type, AVG(price)
FROM titles
WHERE royalty = 10
GROUP BY all type
ORDER BY type
Here is the result set:
type
-----------business
mod_cook
popular_comp
psychology
trad_cook
UNDECIDED
-------------------------17.31
NULL
20.00
14.14
17.97
NULL
48
(6 row(s) affected)
K. Use GROUP BY with ORDER BY
This example finds the average price of each type of book and orders the results by average price.
USE pubs
SELECT type, AVG(price)
FROM titles
GROUP BY type
ORDER BY AVG(price)
Here is the result set:
type
-----------UNDECIDED
mod_cook
psychology
business
trad_cook
popular_comp
-------------------------NULL
11.49
13.50
13.73
15.96
21.48
(6 row(s) affected)
L. Use the HAVING clause
The first example shows a HAVING clause with an aggregate function. It groups the rows in the
titles table by type and eliminates the groups that include only one book. The second example
shows a HAVING clause without aggregate functions. It groups the rows in the titles table by type
and eliminates those types that do not start with the letter p.
USE pubs
SELECT type
FROM titles
GROUP BY type
HAVING COUNT(*) > 1
ORDER BY type
Here is the result set:
type
-----------business
mod_cook
popular_comp
psychology
trad_cook
(5 row(s) affected)
This query uses the LIKE clause in the HAVING clause.
USE pubs
SELECT type
FROM titles
GROUP BY type
49
HAVING type LIKE 'p%'
ORDER BY type
Here is the result set:
type
-----------popular_comp
psychology
(2 row(s) affected)
M. Use HAVING and GROUP BY
This example shows using GROUP BY, HAVING, WHERE, and ORDER BY clauses in one
SELECT statement. It produces groups and summary values but does so after eliminating the titles
with prices under $5. It also organizes the results by pub_id.
USE pubs
SELECT pub_id, SUM(advance), AVG(price)
FROM titles
WHERE price >= $5
GROUP BY pub_id
HAVING SUM(advance) > $15000
AND AVG(price) < $20
AND pub_id > '0800'
ORDER BY pub_id
Here is the result set:
pub_id
------ -------------------------- -------------------------0877
26,000.00
17.89
1389
30,000.00
18.98
(2 row(s) affected)
N. Use HAVING with SUM and AVG
This example groups the titles table by publisher and includes only those groups of publishers who
have paid more than $25,000 in total advances and whose books average more than $15 in price.
USE pubs
SELECT pub_id, SUM(advance), AVG(price)
FROM titles
GROUP BY pub_id
HAVING SUM(advance) > $25000
AND AVG(price) > $15
To see the publishers who have had year-to-date sales greater than $40,000, use this query:
USE pubs
SELECT pub_id, total = SUM(ytd_sales)
FROM titles
GROUP BY pub_id
HAVING SUM(ytd_sales) > 40000
50
If you want to make sure there are at least six books involved in the calculations for each publisher,
use HAVING COUNT(*) > 5 to eliminate the publishers that return totals for fewer than six books.
The query looks like this:
USE pubs
SELECT pub_id, SUM(ytd_sales) AS total
FROM titles
GROUP BY pub_id
HAVING COUNT(*) > 5
Here is the result set:
pub_id
-----0877
1389
total
----44219
24941
(2 row(s) affected)
With this statement, two rows are returned. New Moon Books (0736) is eliminated.
O. Calculate group totals with COMPUTE BY
This example uses two code examples to show the use of COMPUTE BY. The first code example
uses one COMPUTE BY with one aggregate function, and the second code example uses one
COMPUTE BY item and two aggregate functions.
This example calculates the sum of the prices (for prices over $10) for each type of cookbook, in
order first by type of book and then by price of book.
USE pubs
SELECT type, price
FROM titles
WHERE price > $10
AND type LIKE '%cook'
ORDER BY type, price
COMPUTE SUM(price) BY type
Here is the result set:
type
price
------------ --------------------mod_cook
19.9900
(1 row(s) affected)
sum
--------------------19.9900
(1 row(s) affected)
type
-----------trad_cook
trad_cook
trad_cook
price
--------------------11.9500
14.9900
20.9500
51
(3 row(s) affected)
sum
--------------------47.8900
(1 row(s) affected)
This example retrieves the book type, publisher identification number, and price of all cookbooks.
The COMPUTE BY clause uses two different aggregate functions.
USE pubs
SELECT type, pub_id, price
FROM titles
WHERE type LIKE '%cook'
ORDER BY type, pub_id
COMPUTE SUM(price), MAX(pub_id) BY type
Here is the result set:
type
-----------mod_cook
mod_cook
pub_id
-----0877
0877
price
--------------------19.9900
2.9900
(2 row(s) affected)
sum
max
--------------------- ---22.9800
0877
(1 row(s) affected)
type
-----------trad_cook
trad_cook
trad_cook
pub_id
-----0877
0877
0877
price
--------------------20.9500
11.9500
14.9900
(3 row(s) affected)
sum
max
--------------------- ---47.8900
0877
(1 row(s) affected)
P. Calculate grand values using COMPUTE without BY
The COMPUTE keyword can be used without BY to generate grand totals, grand counts, and so on.
This statement finds the grand total of the prices and advances for all types of books over $20.
USE pubs
SELECT type, price, advance
FROM titles
WHERE price > $20
COMPUTE SUM(price), SUM(advance)
52
You can use COMPUTE BY and COMPUTE without BY in the same query. This query finds the
sum of prices and advances by type, and then computes the grand total of prices and advances for
all types of books.
USE pubs
SELECT type, price, advance
FROM titles
WHERE type LIKE '%cook'
ORDER BY type, price
COMPUTE SUM(price), SUM(advance) BY type
COMPUTE SUM(price), SUM(advance)
Here is the result set:
type
-----------mod_cook
mod_cook
price
--------------------2.9900
19.9900
advance
--------------------15000.0000
.0000
(2 row(s) affected)
sum
sum
--------------------- --------------------22.9800
15000.0000
(1 row(s) affected)
type
-----------trad_cook
trad_cook
trad_cook
price
--------------------11.9500
14.9900
20.9500
advance
--------------------4000.0000
8000.0000
7000.0000
(3 row(s) affected)
sum
sum
--------------------- --------------------47.8900
19000.0000
(1 row(s) affected)
sum
sum
--------------------- --------------------70.8700
34000.0000
(1 row(s) affected)
Q. Calculate computed sums on all rows
This example shows only three columns in the select list and gives totals based on all prices and all
advances at the end of the results.
USE pubs
SELECT type, price, advance
FROM titles
COMPUTE SUM(price), SUM(advance)
Here is the result set:
type
price
advance
53
-----------business
business
business
business
mod_cook
mod_cook
UNDECIDED
popular_comp
popular_comp
popular_comp
psychology
psychology
psychology
psychology
psychology
trad_cook
trad_cook
trad_cook
--------------------19.9900
11.9500
2.9900
19.9900
19.9900
2.9900
NULL
22.9500
20.0000
NULL
21.5900
10.9500
7.0000
19.9900
7.9900
20.9500
11.9500
14.9900
--------------------5000.0000
5000.0000
10125.0000
5000.0000
.0000
15000.0000
NULL
7000.0000
8000.0000
NULL
7000.0000
2275.0000
6000.0000
2000.0000
4000.0000
7000.0000
4000.0000
8000.0000
(18 row(s) affected)
sum
sum
--------------------- --------------------236.2600
95400.0000
(1 row(s) affected)
Warning, null value eliminated from aggregate.
R. Use more than one COMPUTE clause
This example finds the sum of the prices of all psychology books, as well as the sum of the prices of
psychology books organized by publisher. You can use different aggregate functions in the same
statement by including more than one COMPUTE BY clause.
USE pubs
SELECT type, pub_id, price
FROM titles
WHERE type = 'psychology'
ORDER BY type, pub_id, price
COMPUTE SUM(price) BY type, pub_id
COMPUTE SUM(price) BY type
Here is the result set:
type
-----------psychology
psychology
psychology
psychology
pub_id
-----0736
0736
0736
0736
price
--------------------7.0000
7.9900
10.9500
19.9900
(4 row(s) affected)
sum
--------------------45.9300
(1 row(s) affected)
54
type
pub_id price
------------ ------ --------------------psychology
0877
21.5900
(1 row(s) affected)
sum
--------------------21.5900
(1 row(s) affected)
sum
--------------------67.5200
(1 row(s) affected)
S. Compare GROUP BY with COMPUTE
The first example uses the COMPUTE clause to calculate the sum for the prices of the different
types of cookbooks. The second example produces the same summary information using only
GROUP BY.
USE pubs
-- Using COMPUTE
SELECT type, price
FROM titles
WHERE type like '%cook'
ORDER BY type, price
COMPUTE SUM(price) BY type
Here is the result set:
type
-----------mod_cook
mod_cook
price
--------------------2.9900
19.9900
(2 row(s) affected)
sum
--------------------22.9800
(1 row(s) affected)
type
-----------trad_cook
trad_cook
trad_cook
price
--------------------11.9500
14.9900
20.9500
(3 row(s) affected)
sum
--------------------47.8900
(1 row(s) affected)
55
This is the second query using GROUP BY:
USE pubs
-- Using GROUP BY
SELECT type, SUM(price)
FROM titles
WHERE type LIKE '%cook'
GROUP BY type
ORDER BY type
Here is the result set:
type
------------ --------------------mod_cook
22.9800
trad_cook
47.8900
(2 row(s) affected)
T. Use SELECT with GROUP BY, COMPUTE, and ORDER BY clauses
This example returns only those rows with current year-to-date sales, and then computes the
average book cost and total advances in descending order by type. Four columns of data are
returned, including a truncated title. All computed columns appear within the select list.
USE pubs
SELECT CAST(title AS char(20)) AS title, type, price, advance
FROM titles
WHERE ytd_sales IS NOT NULL
ORDER BY type DESC
COMPUTE AVG(price), SUM(advance) BY type
COMPUTE SUM(price), SUM(advance)
Here is the result set:
title
-------------------Onions, Leeks, and G
Fifty Years in Bucki
Sushi, Anyone?
type
-----------trad_cook
trad_cook
trad_cook
price
--------------------20.9500
11.9500
14.9900
advance
---------------7000.0000
4000.0000
8000.0000
(3 row(s) affected)
avg
sum
--------------------- --------------------15.9633
19000.0000
(1 row(s) affected)
title
-------------------Computer Phobic AND
Is Anger the Enemy?
Life Without Fear
Prolonged Data Depri
Emotional Security:
type
-----------psychology
psychology
psychology
psychology
psychology
(5 row(s) affected)
avg
sum
price
--------------------21.5900
10.9500
7.0000
19.9900
7.9900
advance
---------------7000.0000
2275.0000
6000.0000
2000.0000
4000.0000
56
--------------------- --------------------13.5040
21275.0000
(1 row(s) affected)
title
-------------------But Is It User Frien
Secrets of Silicon V
type
-----------popular_comp
popular_comp
price
--------------------22.9500
20.0000
advance
---------------7000.0000
8000.0000
(2 row(s) affected)
avg
sum
--------------------- --------------------21.4750
15000.0000
(1 row(s) affected)
title
-------------------Silicon Valley Gastr
The Gourmet Microwav
type
-----------mod_cook
mod_cook
price
--------------------19.9900
2.9900
advance
---------------.0000
15000.0000
(2 row(s) affected)
avg
sum
--------------------- --------------------11.4900
15000.0000
(1 row(s) affected)
title
-------------------The Busy Executive's
Cooking with Compute
You Can Combat Compu
Straight Talk About
type
-----------business
business
business
business
price
--------------------19.9900
11.9500
2.9900
19.9900
(4 row(s) affected)
avg
sum
--------------------- --------------------13.7300
25125.0000
(1 row(s) affected)
sum
sum
--------------------- --------------------236.2600
95400.0000
(1 row(s) affected)
advance
---------------5000.0000
5000.0000
10125.0000
5000.0000
57
U. Use SELECT statement with CUBE
This example shows two code examples. The first example returns a result set from a SELECT
statement using the CUBE operator. The SELECT statement covers a one-to-many relationship
between book titles and the quantity sold of each book. By using the CUBE operator, the statement
returns an extra row.
USE pubs
SELECT SUBSTRING(title, 1, 65) AS title, SUM(qty) AS 'qty'
FROM sales INNER JOIN titles
ON sales.title_id = titles.title_id
GROUP BY title WITH CUBE
ORDER BY title
Here is the result set:
title
----------------------------------------------------------------NULL
But Is It User Friendly?
Computer Phobic AND Non-Phobic Individuals: Behavior Variations
Cooking with Computers: Surreptitious Balance Sheets
...
The Busy Executive's Database Guide
The Gourmet Microwave
You Can Combat Computer Stress!
qty
-----493
30
20
25
15
40
35
(17 row(s) affected)
NULL represents all values in the title column. The result set returns values for the quantity sold of
each title and the total quantity sold of all titles. Applying the CUBE operator or ROLLUP operator
returns the same result.
This example uses the cube_examples table to show how the CUBE operator affects the result set
and uses an aggregate function (SUM). The cube_examples table contains a product name, a
customer name, and the number of orders each customer has made for a particular product.
USE pubs
CREATE TABLE cube_examples
(product_name varchar(30) NULL,
customer_name varchar(30) NULL,
number_of_orders int
NULL
)
INSERT cube_examples (product_name, customer_name,
VALUES ('Filo Mix', 'Romero y tomillo', 10)
INSERT cube_examples (product_name, customer_name,
VALUES ('Outback Lager', 'Wilman Kala', 10)
INSERT cube_examples (product_name, customer_name,
VALUES ('Filo Mix', 'Romero y tomillo', 20)
INSERT cube_examples (product_name, customer_name,
VALUES ('Ikura', 'Wilman Kala', 10)
INSERT cube_examples (product_name, customer_name,
VALUES ('Ikura', 'Romero y tomillo', 10)
INSERT cube_examples (product_name, customer_name,
VALUES ('Outback Lager', 'Wilman Kala', 20)
INSERT cube_examples (product_name, customer_name,
VALUES ('Filo Mix', 'Wilman Kala', 30)
number_of_orders)
number_of_orders)
number_of_orders)
number_of_orders)
number_of_orders)
number_of_orders)
number_of_orders)
58
INSERT cube_examples (product_name, customer_name, number_of_orders)
VALUES ('Filo Mix', 'Eastern Connection', 40)
INSERT cube_examples (product_name, customer_name, number_of_orders)
VALUES ('Outback Lager', 'Eastern Connection', 10)
INSERT cube_examples (product_name, customer_name, number_of_orders)
VALUES ('Ikura', 'Wilman Kala', 40)
INSERT cube_examples (product_name, customer_name, number_of_orders)
VALUES ('Ikura', 'Romero y tomillo', 10)
INSERT cube_examples (product_name, customer_name, number_of_orders)
VALUES ('Filo Mix', 'Romero y tomillo', 50)
First, issue a typical query with a GROUP BY clause and the result set.
USE pubs
SELECT product_name, customer_name, SUM(number_of_orders)
FROM cube_examples
GROUP BY product_name, customer_name
ORDER BY product_name
The GROUP BY causes the result set to form groups within groups. Here is the result set:
product_name
-----------------------------Filo Mix
Filo Mix
Filo Mix
Ikura
Ikura
Outback Lager
Outback Lager
customer_name
-----------------------------Eastern Connection
Romero y tomillo
Wilman Kala
Romero y tomillo
Wilman Kala
Eastern Connection
Wilman Kala
---------40
80
30
20
50
10
30
(7 row(s) affected)
Next, issue a query with a GROUP BY clause by using the CUBE operator. The result set should
include the same information, and super-aggregate information for each of the GROUP BY
columns.
USE pubs
SELECT product_name, customer_name, SUM(number_of_orders)
FROM cube_examples
GROUP BY product_name, customer_name WITH CUBE
The result set for the CUBE operator holds the values from the simple GROUP BY result set above,
and adds the super-aggregates for each column in the GROUP BY clause. NULL represents all
values in the set from which the aggregate is computed. Here is the result set:
product_name
-----------------------------Filo Mix
Filo Mix
Filo Mix
Filo Mix
Ikura
Ikura
Ikura
Outback Lager
Outback Lager
Outback Lager
NULL
customer_name
-----------------------------Eastern Connection
Romero y tomillo
Wilman Kala
NULL
Romero y tomillo
Wilman Kala
NULL
Eastern Connection
Wilman Kala
NULL
NULL
---------40
80
30
150
20
50
70
10
30
40
260
59
NULL
NULL
NULL
Eastern Connection
Romero y tomillo
Wilman Kala
50
100
110
(14 row(s) affected)
Line 4 of the result set indicates that a total of 150 orders for Filo Mix was placed for all customers.
Line 11 of the result set indicates that the total number of orders placed for all products by all
customers is 260.
Lines 12-14 of the result set indicate that the total number of orders for each customer for all
products are 100, 110, and 50, respectively.
V. Use CUBE on a result set with three columns
This example shows two code examples. The first code example produces a CUBE result set with
three columns, and the second example produces a four-column CUBE result set.
The first SELECT statement returns the publication name, title, and quantity of books sold. The
GROUP BY clause in this example includes two columns called pub_name and title. There are
also two one-to-many relationships between publishers and titles and between titles and sales.
By using the CUBE operator, the result set contains more detailed information about the quantities
of titles sold by publishers. NULL represents all values in the title column.
USE pubs
SELECT pub_name, title, SUM(qty) AS 'qty'
FROM sales INNER JOIN titles
ON sales.title_id = titles.title_id INNER JOIN publishers
ON publishers.pub_id = titles.pub_id
GROUP BY pub_name, title
WITH CUBE
Here is the result set:
pub_name
-------------------Algodata Infosystems
Algodata Infosystems
Algodata Infosystems
Algodata Infosystems
Algodata Infosystems
Algodata Infosystems
Binnet & Hardley
Binnet & Hardley
...
NULL
NULL
NULL
NULL
title
qty
---------------------------------------- -----But Is It User Friendly?
30
Cooking with Computers: Surreptitious Ba
25
Secrets of Silicon Valley
50
Straight Talk About Computers
15
The Busy Executive's Database Guide
15
NULL
135
Computer Phobic AND Non-Phobic Individu
20
Fifty Years in Buckingham Palace Kitche
20
...
Sushi, Anyone?
20
The Busy Executive's Database Guide
15
The Gourmet Microwave
40
You Can Combat Computer Stress!
35
(36 row(s) affected)
Increasing the number of columns in the GROUP BY clause shows why the CUBE operator is an ndimensional operator. A GROUP BY clause with two columns returns three more kinds of
60
groupings when the CUBE operator is used. The number of groupings can be more than three,
depending on the distinct values in the columns.
The result set is grouped by the publisher name and then by the book title. The quantity of each title
sold by each publisher is listed in the right-hand column.
NULL in the title column represents all titles. For more information about how to differentiate
specific values and all values in the result set, see Example H. The CUBE operator returns these
groups of information from one SELECT statement:

Quantity of each title that each publisher has sold

Quantity of each title sold

Quantity of titles sold by each publisher

Total number of titles sold by all publishers
Each column referenced in the GROUP BY clause has been cross-referenced with all other columns
in the GROUP BY clause and the SUM aggregate has been reapplied, which produces additional
rows in the result set. Information returned in the result set grows n-dimensionally along with the
number of columns in the GROUP BY clause.
Note Ensure that the columns following the GROUP BY clause have meaningful, real-life
relationships with each other. For example, if you use au_fname and au_lname, the CUBE
operator returns irrelevant information, such as the number of books sold by authors with the
same first name. Using the CUBE operator on a real-life hierarchy, such as yearly sales and
quarterly sales, produces meaningless rows in the result set. It is more efficient to use the
ROLLUP operator.
In this second code example, the GROUP BY clause contains three columns cross-referenced by the
CUBE operator. Three one-to-many relationships exist between publishers and authors, between
authors and titles, and between titles and sales.
By using the CUBE operator, more detailed information is returned about the quantities of titles
sold by publishers.
USE pubs
SELECT pub_name, au_lname, title, SUM(qty)
FROM authors INNER JOIN titleauthor
ON authors.au_id = titleauthor.au_id INNER JOIN titles
ON titles.title_id = titleauthor.title_id INNER JOIN publishers
ON publishers.pub_id = titles.pub_id INNER JOIN sales
ON sales.title_id = titles.title_id
GROUP BY pub_name, au_lname, title
WITH CUBE
The CUBE operator returns this information based on the cross-referenced groupings returned with
the CUBE operator:

Quantity of each title that each publisher has sold for each author

Quantity of all titles each publisher has sold for each author
61

Quantity of all titles each publisher has sold

Total quantity of all titles sold by all publishers for all authors

Quantity of each title sold by all publishers for each author

Quantity of all titles sold by all publishers for each author

Quantity of each title sold by each publisher for all authors

Quantity of each title sold by all publishers for each author
Note The super-aggregate for all publishers, all titles, and all authors is greater than the total
number of sales, because a number of books have more than one author.
A pattern emerges as the number of relationships grow. The pattern of values and NULL in the
report shows which groups have been formed for a summary aggregate. Explicit information about
the groups is provided by the GROUPING function.
62
W. Use the GROUPING function with CUBE
This example shows how the SELECT statement uses the SUM aggregate, the GROUP BY
clause, and the CUBE operator. It also uses the GROUPING function on the two columns
listed after the GROUP BY clause.
USE pubs
SELECT pub_name, GROUPING(pub_name),title, GROUPING(title),
SUM(qty) AS 'qty'
FROM sales INNER JOIN titles
ON sales.title_id = titles.title_id INNER JOIN publishers
ON publishers.pub_id = titles.pub_id
GROUP BY pub_name, title
WITH CUBE
The result set has two columns containing 0 and 1 values, which are produced by the
GROUPING(pub_name) and GROUPING(title) expressions.
Here is the result set:
pub_name
title
qty
-------------------- --- ------------------------- --- ----------Algodata Infosystems
0 But Is It User Friendly?
0
30
Algodata Infosystems
0 Cooking with Computers: S
0
25
Algodata Infosystems
0 Secrets of Silicon Valley
0
50
Algodata Infosystems
0 Straight Talk About Compu
0
15
Algodata Infosystems
0 The Busy Executive's Data
0
15
Algodata Infosystems
0 NULL
1
135
Binnet & Hardley
0 Computer Phobic AND Non-P
0
20
Binnet & Hardley
0 Fifty Years in Buckingham
0
20
...
...
NULL
1 The Busy Executive's Data
0
15
NULL
1 The Gourmet Microwave
0
40
NULL
1 You Can Combat Computer S
0
35
(36 row(s) affected)
X. Use the ROLLUP operator
This example shows two code examples. This first example retrieves the product name, customer
name, and the sum of orders placed and uses the ROLLUP operator.
USE pubs
SELECT product_name, customer_name, SUM(number_of_orders)
AS 'Sum orders'
FROM cube_examples
GROUP BY product_name, customer_name
WITH ROLLUP
Here is the result set:
product_name
customer_name
Sum orders
------------------------------ ------------------------------ ---------Filo Mix
Eastern Connection
40
63
Filo Mix
Filo Mix
Filo Mix
Ikura
Ikura
Ikura
Outback Lager
Outback Lager
Outback Lager
NULL
Romero y tomillo
Wilman Kala
NULL
Romero y tomillo
Wilman Kala
NULL
Eastern Connection
Wilman Kala
NULL
NULL
80
30
150
20
50
70
10
30
40
260
(11 row(s) affected)
This second example performs a ROLLUP operation on the company and department columns and
totals the number of employees.
The ROLLUP operator produces a summary of aggregates. This is useful when summary
information is needed but a full CUBE provides extraneous data or when you have sets within sets.
For example, departments within a company are a set within a set.
USE pubs
CREATE TABLE personnel
(
company_name varchar(20),
department
varchar(15),
num_employees int
)
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
personnel
personnel
personnel
personnel
personnel
personnel
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
('Du monde entier', 'Finance', 10)
('Du monde entier', 'Engineering', 40)
('Du monde entier', 'Marketing', 40)
('Piccolo und mehr', 'Accounting', 20)
('Piccolo und mehr', 'Personnel', 30)
('Piccolo und mehr', 'Payroll', 40)
In this query, the company name, department, and the sum of all employees for the company
become part of the result set, in addition to the ROLLUP calculations.
SELECT company_name, department, SUM(num_employees)
FROM personnel
GROUP BY company_name, department WITH ROLLUP
Here is the result set:
company_name
-------------------Du monde entier
Du monde entier
Du monde entier
Du monde entier
Piccolo und mehr
Piccolo und mehr
Piccolo und mehr
Piccolo und mehr
NULL
department
--------------Engineering
Finance
Marketing
NULL
Accounting
Payroll
Personnel
NULL
NULL
(9 row(s) affected)
Y. Use the GROUPING function
----------40
10
40
90
20
40
30
90
180
64
This example adds three new rows to the cube_examples table. Each of the three records NULL in
one or more columns to show only the ROLLUP function produces a value of 1 in the grouping
column. In addition, this example modifies the SELECT statement that was used in the earlier
example.
USE pubs
-- Add first row with a NULL customer name and 0 orders.
INSERT cube_examples (product_name, customer_name, number_of_orders)
VALUES ('Ikura', NULL, 0)
-- Add second row with a NULL product and NULL customer with real value
-- for orders.
INSERT cube_examples (product_name, customer_name, number_of_orders)
VALUES (NULL, NULL, 50)
-- Add third row with a NULL product, NULL order amount, but a real
-- customer name.
INSERT cube_examples (product_name, customer_name, number_of_orders)
VALUES (NULL, 'Wilman Kala', NULL)
SELECT product_name AS Prod, customer_name AS Cust,
SUM(number_of_orders) AS 'Sum Orders',
GROUPING(product_name) AS 'Grp prod_name',
GROUPING(customer_name) AS 'Grp cust_name'
FROM cube_examples
GROUP BY product_name, customer_name
WITH ROLLUP
The GROUPING function can be used only with CUBE or ROLLUP. The GROUPING function
returns 1 when an expression evaluates to NULL, because the column value is NULL and
represents the set of all values. The GROUPING function returns 0 when the corresponding column
(whether it is NULL or not) did not come from either the CUBE or ROLLUP options as a syntax
value. The returned value has a tinyint data type.
Here is the result set:
Prod
------------NULL
NULL
NULL
Filo Mix
Filo Mix
Filo Mix
Filo Mix
Ikura
Ikura
Ikura
Ikura
Outback Lager
Outback Lager
Outback Lager
NULL
Cust
-----------------NULL
Wilman Kala
NULL
Eastern Connection
Romero y tomillo
Wilman Kala
NULL
NULL
Romero y tomillo
Wilman Kala
NULL
Eastern Connection
Wilman Kala
NULL
NULL
Sum Orders
----------50
NULL
50
40
80
30
150
0
20
50
70
10
30
40
310
Grp prod_name
------------0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
(15 row(s) affected)
Z. Use SELECT with GROUP BY, an aggregate function, and ROLLUP
Grp cust_name
------------0
0
1
0
0
0
1
0
0
0
1
0
0
1
1
65
This example uses a SELECT query that contains an aggregate function and a GROUP BY clause,
which lists pub_name, au_lname, and title, in that order.
USE pubs
SELECT pub_name, au_lname, title, SUM(qty) AS 'SUM'
FROM authors INNER JOIN titleauthor
ON authors.au_id = titleauthor.au_id INNER JOIN titles
ON titles.title_id = titleauthor.title_id INNER JOIN publishers
ON publishers.pub_id = titles.pub_id INNER JOIN sales
ON sales.title_id = titles.title_id
GROUP BY pub_name, au_lname, title
WITH ROLLUP
By using the ROLLUP operator, these groupings are created by moving right to left along the list of
columns.
pub_name
pub_name
pub_name
NULL
au_lname
au_lname
NULL
NULL
title
NULL
NULL
NULL
SUM(qty)
SUM(qty)
SUM(qty)
SUM(qty)
NULL represents all values for that column.
If you use the SELECT statement without the ROLLUP operator, the statement creates a single
grouping. The query returns a sum value for each unique combination of pub_name, au_lname,
and title.
pub_name
au_lname
title
SUM(qty)
Compare these examples with the groupings created by using the CUBE operator on the same
query.
pub_name
pub_name
pub_name
NULL
NULL
NULL
pub_name
NULL
au_lname
au_lname
NULL
NULL
au_lname
au_lname
NULL
NULL
title
SUM(qty)
NULL
SUM(qty)
NULL
SUM(qty)
NULL
SUM(qty)
title
SUM(qty)
NULL
SUM(qty)
title
SUM(qty)
title
SUM(qty)
The groupings correspond to the information returned in the result set. NULL in the result set
represents all values in the column. The ROLLUP operator returns the following data when the
columns (pub_name, au_lname, title) are in the order listed in the GROUP BY clause:

Quantity of each title that each publisher has sold for each author

Quantity of all titles each publisher has sold for each author

Quantity of all titles each publisher has sold

Total quantity of all titles sold by all publishers for all authors
Here is the result set:
pub_name
au_lname
title
SUM
66
----------------Algodata Infosys
Algodata Infosys
Algodata Infosys
Algodata Infosys
Algodata Infosys
...
New Moon Books
New Moon Books
New Moon Books
NULL
-----------Bennet
Bennet
Carson
Dull
Dull
White
White
NULL
NULL
------------------------------------ --The Busy Executive's Database Guide 15
NULL
15
NULL
30
Secrets of Silicon Valley
50
NULL
50
...
Prolonged Data Deprivation: Four
15
NULL
15
NULL
316
NULL
791
(49 row(s) affected)
The GROUPING function can be used with the ROLLUP operator or with the CUBE operator. You
can apply this function to one of the columns in the select list. The function returns either 1 or 0
depending upon whether the column is grouped by the ROLLUP operator.
a. Use the INDEX optimizer hint
This example shows two ways to use the INDEX optimizer hint. The first example shows how to
force the optimizer to use a nonclustered index to retrieve rows from a table and the second
example forces a table scan by using an index of 0.
-- Use the specifically named INDEX.
USE pubs
SELECT au_lname, au_fname, phone
FROM authors WITH (INDEX(aunmind))
WHERE au_lname = 'Smith'
Here is the result set:
au_lname
au_fname
phone
-------------------------------------- -------------------- ---------Smith
Meander
913 843-0462
(1 row(s) affected)
-- Force a table scan by using INDEX = 0.
USE pubs
SELECT emp_id, fname, lname, hire_date
FROM employee (index = 0)
WHERE hire_date > '10/1/1994'
b. Use OPTION and the GROUP hints
This example shows how the OPTION (GROUP) clause is used with a GROUP BY clause.
USE pubs
SELECT a.au_fname, a.au_lname, SUBSTRING(t.title, 1, 15)
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id
GROUP BY a.au_lname, a.au_fname, t.title
ORDER BY au_lname ASC, au_fname ASC
OPTION (HASH GROUP, FAST 10)
c. Use the UNION query hint
67
This example uses the MERGE UNION query hint.
USE pubs
SELECT *
FROM authors a1
OPTION (MERGE UNION)
SELECT *
FROM authors a2
d. Use a simple UNION
The result set in this example includes the contents of the ContactName, CompanyName, City,
and Phone columns of both the Customers and SouthAmericanCustomers tables.
USE Northwind
GO
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'SouthAmericanCustomers')
DROP TABLE SouthAmericanCustomers
GO
-- Create SouthAmericanCustomers table.
SELECT ContactName, CompanyName, City, Phone
INTO SouthAmericanCustomers
FROM Customers
WHERE Country IN ('USA', 'Canada')
GO
-- Here is the simple union.
USE Northwind
SELECT ContactName, CompanyName, City, Phone
FROM Customers
WHERE Country IN ('USA', 'Canada')
UNION
SELECT ContactName, CompanyName, City, Phone
FROM SouthAmericanCustomers
ORDER BY CompanyName, ContactName ASC
GO
e. Use SELECT INTO with UNION
In this example, the INTO clause in the first SELECT statement specifies that the table named
CustomerResults holds the final result set of the union of the designated columns of the
Customers and SouthAmericanCustomers tables.
USE Northwind
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'CustomerResults')
DROP TABLE CustomerResults
GO
USE Northwind
SELECT ContactName, CompanyName, City, Phone INTO CustomerResults
FROM Customers
WHERE Country IN ('USA', 'Canada')
UNION
SELECT ContactName, CompanyName, City, Phone
FROM SouthAmericanCustomers
ORDER BY CompanyName, ContactName ASC
GO
f. Use UNION of two SELECT statements with ORDER BY
68
The order of certain parameters used with the UNION clause is important. This example shows the
incorrect and correct use of UNION in two SELECT statements in which a column is to be renamed
in the output.
/* INCORRECT */
USE Northwind
GO
SELECT City
FROM Customers
ORDER BY Cities
UNION
SELECT Cities = City
FROM SouthAmericanCustomers
GO
/* CORRECT */
USE Northwind
GO
SELECT Cities = City
FROM Customers
UNION
SELECT City
FROM SouthAmericanCustomers
ORDER BY Cities
GO
g. Use UNION of three SELECT statements showing the effects of ALL and parentheses
These examples use UNION to combine the results of three tables, in which all have the same 5
rows of data. The first example uses UNION ALL to show the duplicated records, and returns all 15
rows. The second example uses UNION without ALL to eliminate the duplicate rows from the
combined results of the three SELECT statements, and returns 5 rows.
The final example uses ALL with the first UNION, and parentheses around the second UNION that
is not using ALL. The second UNION is processed first because it is in parentheses, and returns 5
rows because the ALL option is not used and the duplicates are removed. These 5 rows are
combined with the results of the first SELECT through the UNION ALL keywords, which does not
remove the duplicates between the two sets of 5 rows. The final result has 10 rows.
USE Northwind
GO
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'CustomersOne')
DROP TABLE CustomersOne
GO
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'CustomersTwo')
DROP TABLE CustomersTwo
GO
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'CustomersThree')
DROP TABLE CustomersThree
GO
USE Northwind
GO
SELECT ContactName, CompanyName, City, Phone INTO CustomersOne
FROM Customers
WHERE Country = 'Mexico'
GO
69
SELECT ContactName, CompanyName, City, Phone INTO CustomersTwo
FROM Customers
WHERE Country = 'Mexico'
GO
SELECT ContactName, CompanyName, City, Phone INTO CustomersThree
FROM Customers
WHERE Country = 'Mexico'
GO
-- Union ALL
SELECT ContactName
FROM CustomersOne
UNION ALL
SELECT ContactName
FROM CustomersTwo
UNION ALL
SELECT ContactName
FROM CustomersThree
GO
USE Northwind
GO
SELECT ContactName
FROM CustomersOne
UNION
SELECT ContactName
FROM CustomersTwo
UNION
SELECT ContactName
FROM CustomersThree
GO
USE Northwind
GO
SELECT ContactName
FROM CustomersOne
UNION ALL
(
SELECT ContactName
FROM CustomersTwo
UNION
SELECT ContactName
FROM CustomersThree
)
GO
Download