Database Engine
SQL Server components can be divided into two
broad categories:
Those within the engine
External tools (e.g., user interfaces and
components)
Database Engine Contd…
Called the Relational Engine, is the core of SQL
Server
Within the Relational Engine are several key
processes and components, including the
following:
Algebrizer: Checks the syntax and transforms a query
to an internal representation that is used by the
following components.
Query Optimizer: SQL Server’s Query Optimizer
determines how to best process the query based on the
costs of different types of query-execution operations.
Query Engine, or Query Processor: Executes the queries
according to the plan generated by the Query Optimizer.
Database Engine Contd..
Storage Engine: Works for the Query Engine
and handles the actual reading from and writing
to the disk.
The Buffer Manager: Pre-fetches data from the
data file(s) into memory
Resource Monitor: Optimizes the query plan
cache by responding to memory pressure
Lock Manager: Dynamically manages the scope
of locks
SQLOS: Has direct control of the available
resources (memory, threads, I/O request, etc
SQL Server Services
The following components are client processes for
SQL Server used to control, or communicate
with,SQL Server.
SQL Server Agent : is an optional process that,
when running, executes SQL jobs and handles
other automated tasks.
Database Mail : enables SQL Server to send mail
to an external mailbox through SMTP.
Distributed Transaction Coordinator (DTC): is
a process that handles dual-phase commits for
transactions that span multiple SQL Servers.
SQL Statement Categories
DDL (Data Definition Language)
-Used to create and manage the objects in a
database
-CREATE, ALTER, DROP
DCL (Data Control Language)
– Controls data access and ensure security
– GRANT, DENY
DML (Data Manipulation Language)
– To work with data
– INSERT, UPDATE, SELECT, DELETE,MERGE
Understanding Query Flow
Syntactical flow of the query statement
SELECT [DISTINCT][TOP (n)] *, columns, or expressions
[FROM data source(s)]
[JOIN data source
ON condition](may include multiple joins)
[WHERE conditions]
[GROUP BY columns]
[HAVING conditions]
[ORDER BY Columns];
The SELECT statement begins with a list of columns
or expressions.
The simplest possible valid SELECT statement is as
follows:
SELECT 1;
From Clause Data Sources
The first logical component of a typical SQL
SELECT statement is the FROM clause.
Possible data sources
Local SQL Server tables,view
Subqueries serving as derived tables, also called
subselects or in-line views
Where Conditions
The WHERE conditions filter the output of the
FROM clause and restrict the rows that will be
returned in the result set.
The conditions can refer to the data within the
tables, expressions, built-in SQL Server scalar
functions, or user-defined functions.
The WHERE conditions can also make use of
several possible comparison operators and
wildcards
multiple WHERE conditions may be combined
using Boolean AND, OR, and NOT operators.
Columns, Stars, Aliases, and
Expressions
The star : Includes all columns in their table order.
Aliases : The column name in resultset can be changed using a column alias.
The following code demonstrates adding aliases to columns:
EXAMPLE :
SELECT ProductName AS Product,
‘abc’,
ActiveDate + 365 AS OneYearSalesDate
FROM Product
Result:
Product OneYearSalesDate
-------------------------- ---- ------------------------
Basic Box Kite 21 inch abc 2003-07-22 20:59:53.967
Sky Dancer abc 2003-07-22 20:59:54.000
. . .
The first column’s name is changed from ProductName to Product by means of an alias. The second
column is an expression without an alias, so it has no column name. A better practice is to name
expression columns using an alias, as demonstrated in the third column.
Ordering the Result Set
SQL Server usually returns the data in the order of
the primary key ,but there’s no logical guarantee
of that order.
The only correct way to sort the results is with an
ORDER BY clause.
Specifying the order by using column names
The best way to sort the result set is to completely
spell out the ORDER BY columns:
USE CHA2;
SELECT FirstName, LastName
FROM dbo.Customer
ORDER BY LastName, FirstName;
Select Distinct
The following example demonstrates DISTINCT
SELECT DISTINCT TourName
FROM Event
JOIN Tour
ON Event.TourID = Tour.TourID;
Top ()
TOP() predicate tells SQL Server to return only a
few rows (either a fixed number or a percentage
TOP() works hand-in-hand with ORDER BY
The following query finds the top 3 percent of
prices in the price table. The price table allows
each product to have multiple prices, according to
the effective date:
SELECT TOP (3) PERCENT p.Code, p.ProductName,
pr.Price,
CONVERT(VARCHAR(10),pr.EffectiveDate,1) AS PriceDate
FROM Product AS p
JOIN Price AS pr ON p.ProductID = pr.ProductID
ORDER BY pr.Price DESC;
Example TOP
The next query locates the three lowest prices
in the price table:
SELECT TOP (3) p.Code, p.ProductName,
pr.Price,
CONVERT(VARCHAR(10),pr.EffectiveDate,1) AS
PriceDate
FROM Product AS p
JOIN Price AS pr ON p.ProductID = pr.ProductID
ORDER BY pr.Price;
The with ties option
The WITH TIES option is important to the
TOP() predicate. It allows the last place to
include multiple rows if those rows have equal
values in the columns used in the ORDER BY
clause.
SELECT TOP (3) WITH TIES p.ProductCode,
p.ProductName, pr.Price,
CONVERT(varchar(10),pr.EffectiveDate,1) AS
PriceDate
FROM Product AS p
JOIN Price AS pr ON p.ProductID = pr.ProductID
ORDER BY pr.Price;
Relational operators
■ Restrict: Returns the rows that meet a certain
criterion
■ Project: Returns selected columns, or calculated
data, from a data set
■ Product: Relational multiplication that returns all
possible combinations
of data between two data sets
■ Union: Relational addition and subtraction that
merges two tables
vertically by stacking one table above another table
and lining up the
columns
Relational operators
■ Intersection: Returns the rows common to two
data sets
■ Difference: Returns the rows unique to one data
set
■ Join: Returns the horizontal merger of two tables,
matching up rows
based on common data
■ Divide: The inverse of relational multiplication,
returns rows in one
data set that match every row in a corresponding
data set
Creating inner joins within SQL
code
Using T- SQL code, joins are specified within the
FROM portion of the SELECT statement. The
keyword
JOIN identifies the second table, and the ON
clause defines the common ground between the
two tables.
The default type of join is an inner join, so the
keyword INNER is optional. For clarity, however, I
recommend
always including it:
SELECT *
FROM Table1
[INNER] JOIN Table2
ON Table1.column = Table2.column;
Example :
USE OBXKites;
SELECT LastName, FirstName, ProductName
FROM dbo.Contact C
INNER JOIN dbo.[Order] O
ON C.ContactID = O.ContactID
INNER JOIN dbo.OrderDetail OD
ON O.OrderID = OD.OrderID
INNER JOIN dbo.Product P
ON OD.ProductID = P.ProductID
INNER JOIN dbo.ProductCategory PC
ON P.ProductCategoryID = PC.ProductCategoryID
WHERE ProductCategoryName = ‘Kite’
ORDER BY LastName, FirstName;
Key points about inner joins
■ They only match rows with a common value.
■ The order of the data sources is unimportant.
■ They can appear to multiply rows.
■ Newer ANSI 92 style is the best way to write
them.
Outer Join
In SQL code, an outer join is declared by the
keywords LEFT OUTER or RIGHT OUTER
before the JOIN
(technically, the keyword OUTER is optional):
SELECT *
FROM Table1
LEFT|RIGHT [OUTER] JOIN Table2
ON Table1.column = Table2.column;
Example : Outer Join
It returns all contacts regardless of any orders,changing the join type from inner to left
outer is all that’s required, as follows:
SELECT ContactCode, OrderNumber
FROM dbo.Contact
LEFT OUTER JOIN dbo.[Order]
ON [Order].ContactID = Contact.ContactID
ORDER BY ContactCode;
The left outer join will include all rows from the Contact table and matching rows from
the [Order]
table.
The abbreviated result of the query is as follows:
Contact. [Order].
ContactCode OrderNumber
--------------- -----------
101 1
Self-Joins
A self-join is a join that refers back to the same
table. This type of unary relationship is often
used to
extract data from a reflexive (also called a
recursive) relationship, such as organizational
charts (employee
to boss). Think of a self-join as a table being
joined with a temporary copy of itself.
Example : SelfJoin
USE Family;
SELECT Child.PersonID, Child.FirstName,
Child.MotherID, Mother.PersonID
FROM dbo.Person AS Child
INNER JOIN dbo.Person AS Mother
ON Child.MotherID = Mother.PersonID
WHERE Mother.LastName = ‘Halloway’
AND Mother.FirstName = ‘Audry’;
SubQuery
A subquery is an embedded SQL statement
within an outer query.
Three basic forms are possible when building
a subquery, depending on the data needs and
your favored syntax:
■ Simple subquery
■ Common table expression (CTE)
■ Correlated subquery(expensive queries/division
operator)
Simple Subqueries
Simple subqueries are executed in the following order:
1. The simple subquery is executed once.
2. The results are passed to the outer query.
3. The outer query is executed once.
The most basic simple subquery returns a single (scalar)
value, which is then used as an expression in
the outer query, as follows:
SELECT (SELECT 3) AS SubqueryValue;
Result:
SubqueryValue
--------------
3
Example : Simple
USE OBXKites;
SELECT ProductName
FROM dbo.Product
WHERE ProductCategoryID
= (Select ProductCategoryID
FROM dbo.ProductCategory
Where ProductCategoryName = ‘Kite’);
All, some, and any
Though not as popular as IN, three other
options are worth examining when using a
subquery in a WHERE clause
ALL must be true for every value.
SOME and ANY, which are equivalent
keywords, must be true for some of the values
in the subquery.
Example 1:
SELECT ‘True’ as ‘AllTest’
WHERE 1 < ALL
(SELECT a
FROM
(VALUES
(0),
(3),
(5),
(7),
(9)
) AS ValuesTable(a)
);
Result:
AllTest
--------------
Example 2:
SELECT ‘True’ as ‘SomeTest’
WHERE 5 = SOME
(SELECT a
FROM
(VALUES
(2),
(3),
(5),
(7),
(9)
) AS MyTable(a)
);
Result:
SomeTest
--------------
True
Using scalar subqueries
If the subquery returns a single value
It may then be used anywhere inside the SQL
SELECT statement where an expression might
be used, including
column expressions
JOIN conditions
WHERE conditions
HAVING conditions.
Scalar Subqueries: Examples
Scalar Subqueries in CASE Expressions
SELECT employee_id, last_name,
(CASE
WHEN department_id =
THEN 'Canada' ELSE 'USA' END) location
FROM employees;
(SELECT department_id FROM departments
WHERE location_id = 1800)
SELECT employee_id, last_name
FROM employees e
ORDER BY
20
(SELECT department_name
FROM departments d
WHERE e.department_id = d.department_id);
Using subqueries as tables
In the same way that a view may be used in the place of a
table within the FROM clause of a SELECT
statement, a subquery in the form of a derived table can
replace any table, provided the subquery has an alias.
SELECT P.Code,
P.ProductName,
Sales.QuantitySold
FROM dbo.Product AS P
JOIN (SELECT ProductID, SUM(Quantity) AS QuantitySold
FROM dbo.OrderDetail
GROUP BY ProductID) AS Sales
ON P.ProductID = Sales.ProductID
ORDER BY P.Code;
Correlating in the where clause
The logical execution order is as follows:
1. The outer query is executed once.
2. The subquery is executed once for every
row in the outer query, substituting the
values from the outer query into each
execution of the subquery.
3. The subquery’s results are integrated into
the result set.
Correlated Subqueries->Division
operator
Correlated subqueries are used for row-by-row
processing. Each subquery is executed once for
every row of the outer query.
GET
candidate row from outer query
EXECUTE
inner query using candidate row value
USE
values from inner query to qualify or
disqualify candidate row
Correlated Subqueries
SELECT column1, column2, ...
FROM table1
WHERE column1 operator
(SELECT colum1, column2
FROM table2
WHERE expr1 =
.expr2);
outer
outer
The subquery references a column from
a table in the parent query.
SELECT last_name, salary, department_id
FROM employees outer
WHERE salary >
Using Correlated Subqueries
Find all employees who earn more than the
average salary in their department.
Each time a row from
the outer query
is processed, the
inner query is
evaluated.
(SELECT AVG(salary)
FROM employees
WHERE department_id =
outer.department_id) ;
Using Correlated Subqueries
SELECT e.employee_id, last_name,e.job_id
FROM employees e
WHERE 2 <= (SELECT COUNT(*)
FROM job_history
WHERE employee_id = e.employee_id);
Display details of those employees who have switched
jobs at least twice.
Correlated UPDATE
Use a correlated subquery to update rows
in one table based on rows from another
table.
UPDATE table1 alias1
SET column = (SELECT expression
FROM table2 alias2
WHERE alias1.column =
alias2.column);
Correlated UPDATE
• Denormalize the EMPLOYEES table by adding a
column to store the department name.
• Populate the table by using a correlated update.
UPDATE employees e
SET department_name =
(SELECT department_name
FROM departments d
WHERE e.department_id = d.department_id);
Common table expressions
The common table expression (CTE) defines what
could be considered a temporary view
Can be referenced just like a view in the same query
WITH CTEName (Column aliases)
AS (Simple Subquery)
SELECT. . .
FROM CTEName;
Example
WITH CTEQuery (ProductCategoryID)
AS (Select ProductCategoryID
from dbo.ProductCategory
Where ProductCategoryName = ‘Kite’)
CTE : Example
WITH
dept_costs AS (
SELECT d.department_name, SUM(e.salary) AS dept_total
FROM employees e, departments d
WHERE e.department_id = d.department_id
GROUP BY d.department_name),
avg_cost AS (
SELECT SUM(dept_total)/COUNT(*) AS dept_avg
FROM dept_costs)
SELECT *
FROM dept_costs
WHERE dept_total >
(SELECT dept_avg
FROM avg_cost)
ORDER BY department_name;
Set Operators
UNION
UNION ALL
EXCEPT
INTERSECT
The basic rules for combining the result sets are the
following:
The number and the order of the columns must be the
same in all queries.
The data types must be compatible.
Tables Used in This Lesson
The tables used in this lesson are:
EMPLOYEES: Provides details regarding all
current employees
JOB_HISTORY: Records the details of the start
date and end date of the former job, and the job
identification number and department when an
employee switches jobs
The UNION Operator
The UNION operator returns results from both
queries
after eliminating duplications.
A B
Using the UNION Operator
Display the current and previous job details of all
employees. Display each employee only once.
SELECT employee_id, job_id
FROM employees
UNION
SELECT employee_id, job_id
FROM job_history;
The UNION ALL Operator
A B
The UNION ALL operator returns results from both queries,
including all duplications.
Using the UNION ALL Operator
Display the current and previous departments of
all employees.
SELECT employee_id, job_id, department_id
FROM employees
UNION ALL
SELECT employee_id, job_id, department_id
FROM job_history
ORDER BY employee_id;
Using the INTERSECT Operator
Display the employee IDs and job IDs of
employees who currently have a job title that they
held before beginning their tenure with the
company.
SELECT employee_id, job_id
FROM employees
INTERSECT
SELECT employee_id, job_id
FROM job_history;
The EXCEPT Operator
SELECT employee_id,job_id
FROM employees
EXCEPT
SELECT employee_id,job_id
FROM job_history;
SET Operator Guidelines
The expressions in the SELECT lists must
match in number and data type.
Parentheses can be used to alter the
sequence of execution.
The ORDER BY clause:
Can appear only at the very end of the
statement
Will accept the column name, aliases from the
first SELECT statement, or the positional
notation
The SET Operators
Duplicate rows are automatically eliminated
except in UNION ALL.
Column names from the first query appear in the
result.
The output is sorted in ascending order by
default except in UNION ALL.
Matching the SELECT
Statements
Using the UNION operator, display the department
ID,
location, and hire date for all employees.
SELECT department_id, TO_NUMBER(null)
location, hire_date
FROM employees
UNION
SELECT department_id, location_id, TO_DATE(null)
FROM departments;
Matching the SELECT
Statement
Using the UNION operator, display the employee
ID, job ID, and salary of all employees.
SELECT employee_id, job_id,salary
FROM employees
UNION
SELECT employee_id, job_id,0
FROM job_history;
Example
SELECT 15%4 AS Modulo,
FLOOR(1.25) AS [Floor], CEILING(1.25) AS [Ceiling];
Result:
Modulo Floor Ceiling
----------- ----- -------
3 1 2
The + operator is used for both mathematical expressions and string concatenation. This operator is
different from the Visual Basic symbol for string concatenation, the ampersand (&):
SELECT 123 + 456 AS Addition,
‘abc’ + ‘defg’ AS Concatenation;
Result:
Addition Concatenation
----------- ------------------
579 abcdefg
Data from table columns and string literals may be concatenated to return custom data:
Use OBXKites
SELECT ‘Product: ’ + ProductName AS Product
FROM Product;
Result:
Product
Boolean and
A Boolean ‘‘and’’ (represented by the ampersand character, &) returns a value of true only if both inputs are true
(or 1 for mathematical bit operations).
If either or both are false (or 0 for mathematical bit operations), then the ‘‘and’’ will return a value of 1, as follows:
SELECT 1 & 1;
Result:
1
Another ‘‘and’’ example:
SELECT 1 & 0;
Result:
0
‘‘And’’ing two integers is illustrated as follows:
decimal 3 = binary 011
decimal 5 = binary 101
3 AND 5
decimal 1 = binary 001
SELECT 3 & 5;
Result:
1
Boolean or
The Boolean OR operator, the vertical pipe character (|), returns true if either input is true:
SELECT 1 | 1;
Result:
1
The following SELECT statement combines a set (true or 1) and a cleared (false or 0) bit using the
bitwise or operator:
SELECT 1 | 0;
Result:
1
ORing two integers can be illustrated as follows:
decimal 3 = binary 011
decimal 5 = binary 101
3 OR 5
decimal 7 = binary 111
SELECT 3 | 5;
Result:
7
Case expressions
SQL Server’s CASE expression is a flexible and excellent
means of building dynamic expressions
The CASE statement has two forms, simple and searched,
described in the following sections.
Simple case
USE OBXKites;
SELECT CustomerTypeName,
CASE IsDefault
WHEN 1 THEN ‘default type’
WHEN 0 THEN ‘possible’
ELSE ‘-’
END AS AssignStatus
FROM CustomerType;
Boolean case
The Boolean form of case (called the searched )
is more flexible than the simple
Not only can each WHEN condition include
comparisons other than =, but the comparison
may also reference different columns:
SELECT
CASE
WHEN 1<0 THEN ‘Reality is gone.’
WHEN CURRENT_TIMESTAMP = ‘20051130’
THEN ‘David gets his driver’’s license.’
WHEN 1>0 THEN ‘Life is normal.’
END AS RealityCheck;
Working with nulls
The relational database model represents
missing data using null.
Technically, null means ‘‘value absent’’ and it’s
commonly understood to mean ‘‘unknown.’’
In practice, null can indicate that the data has
not yet been entered into the database or that
the column does not apply to the particular
row.
SELECT 1 + NULL;
Result:
NULL
Consider this simple test which proves that null does not equal null:
IF NULL = NULL
SELECT ‘=’;
ELSE
SELECT ‘<> ’;
Result:
<>
Because the = and <> operators can’t check for nulls, SQL includes two
special operators, IS and IS NOT, to test for equivalence to special values,
as follows:
WHERE Expression IS NULL
Repeating the simple test, the IS search operator works as advertised:
IF NULL IS NULL
SELECT ‘Is’;
ELSE
SELECT ‘Is Not’;
Result:
Is
Handling nulls With functions
When you are supplying data to reports, to end
users, or to some applications, a null value will be
less than welcome.
Often a null must be converted to a valid value so
that the data may be understood, or so the
expression won’t fail.
Nulls require special handling when used within
expressions, and SQL includes a few functions
ISNULL() convert nulls to usable values
COALESCE() convert nulls to usable values, and
NULLIF() creates a null if the specified condition is
met.
Using the COALESCE()
function
COALESCE() accepts a list of expressions or columns
and returns the first non-null value, as follows:
COALESCE(expression, expression, ...)
Functionally, COALESCE() is the same as the
following case expression:
CASE
WHEN expression1 IS NOT NULL THEN expression1
WHEN expression2 IS NOT NULL THEN expression2
WHEN expression3 IS NOT NULL THEN expression3
...
ELSE NULL
END
Example : SELECT COALESCE(NULL, 1+NULL, 1+2,
‘abc’);
Using the ISNULL() function
If the source is not equal to null, then the ISNULL()
function passes the value on.
However, if the source is null, then the second
parameter is substituted for the null, as follows:
ISNULL(source_expression, replacement_value)
Functionally, ISNULL() is similar to the following case
expression:
CASE
WHEN source_expression IS NULL THEN
replacement_value
ELSE source_expression
END
Example : select isnull(null,’N.A.’)
Using the NULLIF() function
The NULLIF() function accepts two
parameters. If they are equal, then it returns a
null; otherwise, it returns the first parameter.
Functionally, NULLIF() is the same as the
following case expression:
CASE
WHEN Expression1 = Expression2 THEN NULL
ELSE Expression1
END
Example : select nullif(1,2)
Scalar Functions
Scalar functions return a single value.
They are commonly used in expressions within
the
SELECT
WHERE
ORDER BY,
GROUP
HAVING
T-SQL code
User information functions
In a client/server environment, it’s good to know who the client is. Toward that end, the
following four functions are very useful, especially for gathering audit information:
■ USER_NAME(): Returns the name of the current user as he or she is known to the database.
When a user is granted access to a database, a username that is different from the server login
name may be assigned.
■ SUSER_SNAME(): Returns the login name by which the user was authenticated to SQL
Server.
If the user was authenticated as a member of a Windows user group, then this function still
returns the user’s Windows login name
■ HOST_NAME(): Returns the name of the user’s workstation.
■ APP_NAME(): Returns the name of the application (if set by the application itself) connected to
SELECT
USER_NAME() AS ‘User’,
SUSER_SNAME() AS ‘Login’,
HOST_NAME() AS ‘Workstation’,
APP_NAME() AS ‘Application’;
Date and time functions
SQL Server stores both the data and the time in a single data type. It also has types for date only,time
only, and zone-aware times.
T-SQL includes several functions to return the current date and time:
■ GetDate(): Returns the current server date and time to the nearest 3 13
milliseconds,
rounded to the nearest value
■ CURRENT_TIMESTAMP: The same as GETDATE() except ANSI standard
■ GetUTCDate(): Returns the current server date converted to Greenwich mean time (also
known as UTC time) to the nearest 3 milliseconds. This is extremely useful for companies that
cross time boundaries.
■ SysDateTime(): Returns the current server date and time to the nearest hundred
nanoseconds
■ SysUTCDateTime(): Returns the current server date converted to Greenwich mean time to
the nearest hundred nanoseconds
■ SYSDATETIMEOFFSET(): Returns a DateTimeOffset value that contains the date and
time of the computer on which the instance of SQL Server is running. The time zone offset is
included.
SELECT GetDate(), CURRENT_TIMESTAMP, GetUTCDate(), SysDateTime(), SysUTCDateTime(),
SYSDATETIMEOFFSET(), ToDateTimeOffset()
Date and time functions
The following four SQL Server date-time functions handle extracting or working with a specific portion
of the date or time stored within a datetime column:
■ DATEADD(date portion, number, date): Returns a new value after adding the number
The query adds 100 hours to the current millisecond:
SELECT DATEADD(hh,100, CURRENT_TIMESTAMP) AS [100HoursFromNow];
■ DateName(date portion, date): Returns the proper name for the selected portion of the
datetime value
This code gets the month and weekday name:
select DATENAME(MONTH,CURRENT_TIMESTAMP) as "Month",
DATENAME(WEEKDAY,CURRENT_TIMESTAMP) As "Day“
This code gets the month and weekday name and displays the results in Italian:
Set language Italian
select DATENAME(MONTH,CURRENT_TIMESTAMP) as "Month",
DATENAME(WEEKDAY,CURRENT_TIMESTAMP) As "Day“
Date Time Functions
■ DatePart(date portion, date): Returns the ordinal number of the selected portion of the datetime value.
SELECT DATEPART(dayofyear, CURRENT_TIMESTAMP) AS DayCount;
SELECT DATEPART(weekday, CURRENT_TIMESTAMP) AS DayWeek;
■ DATEDIFF(date portion, start date, end date): Returns the count of the date portion boundaries
select DATEDIFF(year,’september 4 2008’,’november 10 2009’)
select DATEDIFF(month,’september 4 2008’,’november 10 2009’)
The following query calculates the number of years and days
SELECT
DATEDIFF(yy,’19840520’, CURRENT_TIMESTAMP) AS BirthYears,
DATEDIFF(dd,’19840520’, CURRENT_TIMESTAMP) AS BirthDays;
■ ToDateTimeOffset(expression, time_zone): Returns a DateTimeOffset value
The following example gets the date and time for a given time zone:
SELECT TODATETIMEOFFSET(CURRENT_TIMESTAMP,’-07:00’);
String Functions
■ SUBSTRING(string, starting position, length): Returns a portion of a string.
SELECT SUBSTRING(’ab cdefg’, 3, 2);
■ STUFF(string, insertion position, delete count, string inserted): The STUFF()
function inserts one string into another string. The inserted string may
delete a
specified number of characters as it is being inserted:
SELECT STUFF(’abcdefg’, 3, 2, ‘123’);
Result:
ab123efg
The following code sample uses nested STUFF() functions to format a U.S.
social security
number:
SELECT STUFF(STUFF(’123456789’, 4, 0, ‘-’), 7, 0, ‘-’);
Result:
123-45-6789
String Functions
■ CHARINDEX(search string, string, starting position): Returns the character position of
a string within a string. The third argument is optional and rarely used in practice.
It defaults to 1.
SELECT CHARINDEX(’c’, ‘abcdefg’, 1);
Result:
3
■ PATINDEX(pattern, string): Searches for a pattern, which may include wildcards,
within a string. The following code locates the first position of cd in the string:
SELECT PATINDEX(’%[cd]%’, ‘abdcdefg’);
Result:
3
■ RIGHT(string, count) and Left(string, count): Returns the rightmost or leftmost part of a
string:
SELECT LEFT(’Nielsen’,2) AS ‘ [Left] ‘,
RIGHT(’Nielsen’,2) AS [Right];
String Functions
■ LEN(string): Returns the length of a string:
SELECT LEN(’Supercalifragilisticexpialidocious’) AS [Len];
Result:
Len
-----------
34
■ RTRIM(string) and LTrim(string): Removes leading or trailing spaces.
SELECT RTRIM(’ middle earth ‘) AS [RTrim],
LTRIM(’ middle earth ‘) AS [LTrim];
Result:
RTrim LTrim
--------------- ---------------
middle earth middle earth
■ UPPER(string) and Lower(string): Converts the entire string to uppercase or lowercase.
There’s not much to know about these two functions, illustrated here:
SELECT UPPER(’one TWO tHrEe’) AS UpperCase,
LOWER(’one TWO tHrEe’) AS LowerCase;
Data-Type Conversion
Functions
■ CAST(Input as data type): The ANSI standard SQL means of converting from one data
type to another
SELECT CAST(’Away’ AS NVARCHAR(5)) AS ‘Tom Hanks’
Result:
TOM HANKS
---------
AWAY
■ Another example:
SELECT CAST(123 AS NVARCHAR(15)) AS Int2String
Result:
INT2STRING
---------------
123
■ STR(number, length, decimal): Returns a string from a number:
SELECT STR(123,6,2) AS [Str];
Result:
Str
-----
123.00
Server Environment Information
System functions return information about the
current environment. This section covers the
more commonly used system functions:
■ DB_NAME(): Returns the name of the current
database, as shown in the following example:
SELECT CURRENT_TIMESTAMP AS [Date],
DB_NAME() AS [Database];
Server Environment Information
■ SERVERPROPERTY(): Several useful pieces of information about the server may be determined
from this function, including the following:
■ Collation: The collation type
■ Edition: Enterprise, Developer, Standard, and so on
■ EngineEdition: 2 = Standard, 3 = Enterprise, 4 = Express
■ InstanceName: Null if the default instance
■ ProductVersion: The version number of SQL Server
■ ProductLevel: ‘‘RTM’’ for the initial release-to-manufacturing version, ‘‘SPn’’ for service
packs (n is the service pack number), ‘‘CTP’’ for Community Technology Preview versions
■ ServerName: The full server and instance name
For example, the following code returns SQL Server engine edition and version information for
my current instance of SQL Server:
SELECT
SERVERPROPERTY (’ServerName’) AS ServerName,
SERVERPROPERTY (’Edition’) AS Edition,
SERVERPROPERTY (’ProductVersion’) AS ‘ProductVersion’,
SERVERPROPERTY (’ProductLevel’) AS ProductLevel;
Using the COUNT Function
COUNT(expr) returns the number of rows with
non-null values for the expr.
Display the number of department values in the
EMPLOYEES table, excluding the null values.
SELECT COUNT(commission_pct)
FROM employees
WHERE department_id = 80;
SELECT COUNT(DISTINCT department_id)
FROM employees;
Using the DISTINCT Keyword
COUNT(DISTINCT expr) returns the number
of distinct non-null values of the expr.
Display the number of distinct department values
in the EMPLOYEES table.
Creating Groups of Data
EMPLOYEES
The
average
salary
in
EMPLOYEES
table
for each
department.
4400
…
9500
3500
6400
10033
SELECT column, group_function(column)
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[ORDER BY column];
Creating Groups of Data:
The GROUP BY Clause Syntax
Divide rows in a table into smaller groups by
using the
GROUP BY clause.
SELECT department_id, AVG(salary)
FROM employees
GROUP BY department_id ;
Using the GROUP BY Clause
All columns in the SELECT list that are not in group
functions must be in the GROUP BY clause.
Using the GROUP BY Clause
The GROUP BY column does not have to be in the
SELECT list.
SELECT AVG(salary)
FROM employees
GROUP BY department_id ;
Grouping by More Than One
Column
EMPLOYEES
“Add up the
salaries in
the EMPLOYEES
table
for each job,
grouped by
department.
…
SELECT department_id dept_id, job_id, SUM(salary)
FROM employees
GROUP BY department_id, job_id ;
Using the GROUP BY Clause
on Multiple Columns
Illegal Queries
Using Group Functions
Any column or expression in the SELECT list that is
not an aggregate function must be in the GROUP BY
clause.
SELECT department_id, COUNT(last_name)
FROM employees;
SELECT department_id, COUNT(last_name)
*
ERROR at line 1:
ORA-00937: not a single-group group function
Illegal Queries
Using Group Functions
You cannot use the WHERE clause to restrict groups.
You use the HAVING clause to restrict groups.
You cannot use group functions in the WHERE
clause.
SELECT department_id, AVG(salary)
FROM employees
WHERE AVG(salary) > 8000
GROUP BY department_id;
WHERE AVG(salary) > 8000
*
ERROR at line 3:
ORA-00934: group function is not allowed here
SELECT column, group_function
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[HAVING group_condition]
[ORDER BY column];
Excluding Group Results: The
HAVING Clause
Use the HAVING clause to restrict groups:
1. Rows are grouped.
2. The group function is applied.
3. Groups matching the HAVING clause are
displayed.
Using the HAVING Clause
SELECT department_id, MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary)>10000 ;
SELECT job_id, SUM(salary) PAYROLL
FROM employees
WHERE job_id NOT LIKE '%REP%‘
GROUP BY job_id
HAVING SUM(salary) > 13000
ORDER BY SUM(salary);
Using the HAVING Clause
Building Crosstab Queries
Microsoft introduced the PIVOT method for
coding crosstab queries with SQL Server
2005.
The pivot method deviates from the normal
logical query flow by performing the aggregate
GROUP BY function and generating the
crosstab results as a data source within the
FROM clause.
Building Crosstab Queries
Example
Let's assume the following simple schema:
USE Demodb;
GO
CREATE TABLE dbo.Products ( ProductID INT PRIMARY KEY,
Name NVARCHAR(255) NOT NULL UNIQUE );
INSERT dbo.Products VALUES (1, N'foo'), (2, N'bar'), (3, N'kin');
CREATE TABLE dbo.OrderDetails ( OrderID INT, ProductID INT
NOT NULL FOREIGN KEY REFERENCES
dbo.Products(ProductID), Quantity INT);
INSERT dbo.OrderDetails VALUES (1, 1, 1), (1, 2, 2), (2, 1, 1),
(3, 3, 1);
Building Crosstab Queries
Example
A query to obtain each product's total quantity
ordered
SELECT p.Name, Quantity = SUM(o.Quantity)
FROM dbo.Products AS p INNER JOIN
dbo.OrderDetails AS o ON p.ProductID =
o.ProductID GROUP BY p.Name;
Pivoted Data
SELECT p.[foo], p.[bar], p.[kin] FROM (
SELECT p.Name, o.Quantity FROM
dbo.Products AS p INNER JOIN
dbo.OrderDetails AS o ON p.ProductID =
o.ProductID ) AS j PIVOT ( SUM(Quantity)
FOR Name IN ([foo],[bar],[kin]) ) AS p;
Analytical Functions
Analytic functions also operate on subsets of
rows, similar to aggregate functions in GROUP
BY queries, but they do not reduce the number of
rows returned by the query.
Example :
SELECT empno, deptno, sal,
max(sal) OVER (PARTITION BY deptno) AS ma
x_dept_sal
FROM emp;
Analytic Function Syntax
analytic_function([ arguments ]) OVER
(analytic_clause)
The analytic_clause breaks down into the
following optional elements.
[ query_partition_clause ] [ order_by_clause [
windowing_clause ] ]
query_partition_clause
The query_partition_clause divides the result
set into partitions, or groups, of data.
. If the query_partition_clause is omitted, the
whole result set is treated as a single partition.
Example :
SELECT empno, deptno, sal,
AVG(sal) OVER () AS avg_sal
FROM emp;
Example :
SELECT empno, deptno, sal,
AVG(sal) OVER (PARTITION BY deptno) AS
avg_dept_sal
FROM emp;
RANK()
Example :
SELECT empno, deptno, sal, RANK() OVER
(PARTITION BY deptno ORDER BY sal)
"rank" FROM emp;
DENSE_RANK()
The DENSE_RANK function acts like
the RANK function except that it assigns
consecutive ranks.
Example:
SELECT empno, deptno, sal, DENSE_RANK()
OVER (PARTITION BY deptno ORDER BY
sal) "rank" FROM emp;
LEAD() and LAG()
Syntax:
LAG (value_expression [,offset] [,default]) OVER
([query_partition_clause] order_by_clause)
LEAD (value_expression [,offset] [,default]) OVER
([query_partition_clause] order_by_clause)
value_expression - Can be a column or a built-in
function, except for other analytic functions.
offset - The number of rows preceeding/following the
current row, from which the data is to be retrieved.
The default value is 1.
default - The value returned if the offset is outside the
scope of the window. The default value is NULL.
LEAD and LAG
EXAMPLE – LAG
SELECT empno, ename, job, sal, LAG(sal, 1, 0)
OVER (ORDER BY sal) AS sal_prev, sal -
LAG(sal, 1, 0) OVER (ORDER BY sal) AS sal_diff
FROM emp;
EXAMPLE – LEAD
SELECT empno, ename, job, sal, LEAD(sal, 1,
0) OVER (ORDER BY sal) AS sal_next,
LEAD(sal, 1, 0) OVER (ORDER BY sal) - sal
AS sal_diff FROM emp;