SQL Server’s DISTINCT is different from MS Access’ distinctrow , which eliminates dupli-cates based on data in the source tables, not duplidupli-cates in the result set of the query.. mu
Trang 1TourName -Amazon Trek
Appalachian Trail Bahamas Dive Gauley River Rafting Outer Banks Lighthouses Whereas the first query returned 16 rows, theDISTINCTpredicate in the second query eliminated the
duplicate rows and returned only five unique rows
SQL Server’s DISTINCT is different from MS Access’ distinctrow , which eliminates dupli-cates based on data in the source table(s), not duplidupli-cates in the result set of the query.
Select DISTINCTfunctions as though aGROUP BYclause (discussed in Chapter 12, ‘‘Aggregating
Data’’) exists on every output column
Of course, usingDISTINCTis based on the query’s requirements, so there may be no choice; just be
aware that depending on the size and mix of the data, there may be a performance impact
Top ()
By definition,SELECTworks with sets of data Sometimes, however, it’s only the first few rows from
the set that are of interest For these situations, SQL Server includes several ways to filter the results and
find the top rows
As mentioned earlier, SQL Server will return all the rows from theSELECTstatement by default The
optionalTOP()predicate tells SQL Server to return only a few rows (either a fixed number or a
per-centage) based upon the options specified, as shown in Figure 8-4 A variable can be passed toTOP()
The older syntax for TOP() did not include the parentheses and did not accept a variable.
The newer syntax, with the parentheses, was introduced with SQL Server 2005 and is the best practice moving forward.
TOP()works hand-in-hand withORDER BY It’s theORDER BYclause that determines which rows are
first If theSELECTstatement does not have anORDER BYclause, then theTOP()predicate still works
by returning an unordered sampling of the result set
TheOBXKitessample database is a good place to test theTOP()predicate The following query finds
the top 3 percent of prices in thepricetable Thepricetable 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;
Trang 2Introducing Basic Query Flow 8
Result:
ProductCode ProductName Price PriceDate
-1018 Competition Pro 48" 284.9500 05/01/01
1018 Competition Pro 48" 264.9500 05/01/02
1017 Competition 36" 245.9500 05/20/03
1017 Competition 36" 225.9500 05/01/01
The next query locates the three lowest prices in thepricetable:
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;
Result:
ProductCode ProductName Price PriceDate
-1044 OBX Car Bumper Sticker 7500 05/01/01
1045 OBX Car Window Decal 7500 05/20/01
1045 OBX Car Window Decal 9500 05/20/02
The query looks clean and the result looks good, but unfortunately it’s wrong If you look at the raw
data sorted by price, you’ll actually see three rows with a price of 95 cents TheWITH TIESoption
solves this problem, as described in the following section
Best Practice
By the very nature of the formatting, computer-generated data tends to appear correct Unit testing the
query against a set of data with known results is the only way to check its quality
The number of rows returned by TOP() may be controlled using a variable:
SELECT TOP (@Variable)
For more details about using variables, turn to Chapter 21, ‘‘Programming with T-SQL.’’
The with ties option
TheWITH TIESoption is important to theTOP()predicate It allows the last place to include
Trang 3multi-version of the preceding query includes theWITH TIESoption and correctly results in five rows from
aTOP 3predicate:
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;
Result:
ProductCode ProductName Price PriceDate
-1044 OBX Car Bumper Sticker 7500 05/01/01
1045 OBX Car Window Decal 7500 05/20/01
1045 OBX Car Window Decal .9500 05/20/02
If you are moving from Access to SQL Server, be aware that Access, by default, adds the
WITH TIES option to the TOP() predicate automatically.
An alternative to TOP() is the SET ROWCOUNT command, which limits any DML command
to affecting only n number of rows until it’s turned off with SET ROWCOUNT 0 The issue is that ROWCOUNT isn’t portable either, and it’s been deprecated for INSERT , UPDATE , and DELETE in SQL
Server 2008.
Selecting a random row
There are times when a single random row is needed I use this technique when populating a table with
random names
Using theTOP(1)predicate will return a single row, and sorting the result set bynewid()randomizes
the sort Together they will return a random row each time the query is executed
There is a performance cost to usingTOP(1)andnewid() SQL Server has to add aunique
identifierto every row and then sort by theuniqueidentifier An elegant solution is to add
atablesampleoption to the table when randomly selecting a single row from a very large table
Tablesampleworks by randomly selecting pages within the table and then returning every row from
those pages from thefromclause:
SELECT TOP(1) LastName FROM dbo.LastNames TableSample (10 Percent) ORDER BY NewID();
Trang 4Introducing Basic Query Flow 8
Summary
A wealth of power and flexibility is hidden in the simpleSELECTcommand
The key to understanding the SQL query is understanding that the query is declarative — you’re only
phrasing a question The Query Optimizer figures out how to execute the query, so SQL allows for some
flexibility in the development style of the query
A few of the key points from this chapter include the following:
■ Think through the query in the logical flow of the query, not the syntax flow for the query
■ TheFROMclause can assemble data from ten different types of data sources Think creatively
about where you can find data for your query
■ Never useSELECT *
■ Aliases are a good thing, and always use theAS
■ Be intentional about theWHEREclause Use parentheses Keep the expressions away from the
source column
■ Never trust the sort order to the physical order of the data on the disk If the data needs to be
sorted, then use anORDER BY
From this introduction, the next eight chapters add incrementally more advanced features that augment
the power ofSELECT: incorporating complex expressions, multiple types of joins, subqueries, and
groupings
Welcome to the set-based power of SQL
Trang 6Data Types, Expressions,
and Scalar Functions
IN THIS CHAPTER
Working with expressions and scalar functions
Using logic within a query Working with nulls, strings, and dates
When my son, David, was younger he built incredible monster trucks
and gizmos out of K’NEX construction pieces If you aren’t familiar
with K’NEX, do a Google image search and see the wild things that
kids can build with it
What makes K’NEX cool is that nearly any piece can plug into any other piece
This interconnectivity makes K’NEX flexible In the same way, the
interconnectiv-ity of SQL expressions and functions makes SQL so flexible and powerful
Expressions can retrieve data from a subquery, handle complex logic, convert
data types, and manipulate data If the secret to being a competent SQL database
developer is mastering SQL queries, then wielding expressions and scalar
functions is definitely in the arsenal
An expression is any combination of constants, functions, or formulas that returns
a single value Expressions may be as simple as a hard-coded number, or as
complex as a case expression that includes several formulas and functions
Expressions may be employed in several places within the SQL syntax Nearly
anywhere a value may be used, an expression may be used instead This includes
column values,JOIN ONclauses,WHEREandHAVINGclauses, andORDER BY
columns Expressions can’t be substituted for object names such as table names
or column names
Building Expressions
You can construct SQL expressions from a nearly limitless list of constants,
Trang 7The syntax of SQL keywords is not case sensitive The convention is to use keywords in all upper case I sometimes will use lower case for keywords for a subquery to improve readability.
Depending on the collation setting of the server or database, database, table, and column names, and
even the data itself, might be case sensitive.
TABLE 9-1
Building Expressions
Expression Components Examples
Numeric constants 1, 2, 3, -17, -100
String literals ’LastName’, ‘Employee: ‘, ‘Lifes Great!’
‘19800130’
Mathematical operators (in order of
prece-dence)
*, /, % (remainder), +, -String operator (concatenation) +
Bitwise operators (in order of precedence) not∼, and &, or |, exclusive or ˆ
WHEN 1 THEN ‘on’
ELSE ‘off’
END AS Status
User-defined variables @MyVariable
Scalar functions GetDate(), Radians()
User-defined functions dbo.MyUDF()
Subqueries are covered in Chapter 11, Including Data with Subqueries and CTEs Variables are discussed in Chapter 21, Programming with T-SQL User-defined functions are detailed
in Chapter 25, Building User-Defined Functions.
Operators
While the meaning of many of these expression constants, operators, and expressions is obvious and
common to other programming languages, a few deserve special mention
Trang 8Data Types, Expressions, and Scalar Functions 9
The division mathematical operator (/) is a very common source of errors when integers are divided This
is because there is an implicit truncation of values For instance, 17/9 will give a result of 1 although
it is almost 2 (which 18/9 would yield)
The modulo mathematical operator (%) returns only the remainder of the division Thefloor()(that’s
‘‘deck’’ for sailors) andceiling()mathematical functions, which return the integer rounded down
or up, respectively, are related to it Thefloor()function is the SQL Server equivalent of the BASIC
int()function:
SELECT 15%4 AS Modulo,
FLOOR(1.25) AS [Floor], CEILING(1.25) AS [Ceiling];
Result:
Modulo Floor Ceiling
- -
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
-
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
-Product: Basic Box Kite 21 inch
Product: Dragon Flight
Product: Sky Dancer
Bitwise operators
The bitwise operators are useful for binary manipulation These aren’t typically used in transactional
databases, but they can prove useful for certain metadata operations For example, one way to
determine which columns were updated in a trigger (code that is executed as the result of a data
insert, update, or delete, as covered in Chapter 26, ‘‘Creating DML Triggers’’) is to inspect the
columns_updated()function, which returns a binary representation of those columns The trigger
code can testcolumns_updated()using bitwise operations and respond to updates on a
Trang 9column-by-Boolean bit operators (and, or, and not) are the basic building blocks of digital electronics and binary
programming Whereas digital-electronic Boolean gates operate on single bits, these bitwise operators
work across every bit of the integer family data type (int,smallint,tinyint, andbit) values
Boolean and
A Boolean ‘‘and’’ (represented by the ampersand character,&) returns a value of true only if both inputs
are true (or1for mathematical bit operations) If either or both are false (or0for mathematical bit
operations), then the ‘‘and’’ will return a value of1, 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 BooleanORoperator, the vertical pipe character (|), returns true if either input is true:
SELECT 1 | 1;
Result:
1 The followingSELECTstatement 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
Trang 10Data Types, Expressions, and Scalar Functions 9
decimal 5 = binary 101
3 OR 5
decimal 7 = binary 111
SELECT 3 | 5;
Result:
7
Boolean exclusive or
The ‘‘exclusive or’’ (XOR) bitwise operator, the carat (ˆ), returns a value of true if either input is true,
but not if both are true The operator is shown here:
SELECT 1 ˆ 1;
Result:
0
A set bit XORed with a cleared bit results in a set bit:
SELECT 1 ˆ 0;
Result:
1
XORing two integers can be illustrated as follows:
decimal 3 = binary 011
decimal 5 = binary 101
3 OR 5
decimal 6 = binary 110
Bitwise not
The last bitwise operator, denoted by the tilde (∼), is a bitwise NOT function This bitwise ‘‘not’’ is a
lit-tle different The ‘‘not’’ performs a logical bit reversal for every bit in the expression The result depends
on the data length of the expression For example, the bitwise ‘‘not’’ of a set bit is a cleared bit:
DECLARE @A BIT;
SET @A = 1;
SELECT ∼@A;
Result:
0
The bitwise ‘‘not’’ is not suitable for use with Boolean expressions such asIFconditions The following
code, for example, is invalid:
SELECT * FROM Product WHERE ∼(1=1);
Note that the ‘‘not’’ operator also serves as the one’s complement operator The system known as one’s
complement can be used to represent negative numbers The one’s complement form of a negative