- •Using Your Sybex Electronic Book
- •Acknowledgments
- •Contents at a Glance
- •Introduction
- •Who Should Read This Book?
- •How About the Advanced Topics?
- •The Structure of the Book
- •How to Reach the Author
- •The Integrated Development Environment
- •The Start Page
- •Project Types
- •Your First VB Application
- •Making the Application More Robust
- •Making the Application More User-Friendly
- •The IDE Components
- •The IDE Menu
- •The Toolbox Window
- •The Solution Explorer
- •The Properties Window
- •The Output Window
- •The Command Window
- •The Task List Window
- •Environment Options
- •A Few Common Properties
- •A Few Common Events
- •A Few Common Methods
- •Building a Console Application
- •Summary
- •Building a Loan Calculator
- •How the Loan Application Works
- •Designing the User Interface
- •Programming the Loan Application
- •Validating the Data
- •Building a Math Calculator
- •Designing the User Interface
- •Programming the MathCalculator App
- •Adding More Features
- •Exception Handling
- •Taking the LoanCalculator to the Web
- •Working with Multiple Forms
- •Working with Multiple Projects
- •Executable Files
- •Distributing an Application
- •VB.NET at Work: Creating a Windows Installer
- •Finishing the Windows Installer
- •Running the Windows Installer
- •Verifying the Installation
- •Summary
- •Variables
- •Declaring Variables
- •Types of Variables
- •Converting Variable Types
- •User-Defined Data Types
- •Examining Variable Types
- •Why Declare Variables?
- •A Variable’s Scope
- •The Lifetime of a Variable
- •Constants
- •Arrays
- •Declaring Arrays
- •Initializing Arrays
- •Array Limits
- •Multidimensional Arrays
- •Dynamic Arrays
- •Arrays of Arrays
- •Variables as Objects
- •So, What’s an Object?
- •Formatting Numbers
- •Formatting Dates
- •Flow-Control Statements
- •Test Structures
- •Loop Structures
- •Nested Control Structures
- •The Exit Statement
- •Summary
- •Modular Coding
- •Subroutines
- •Functions
- •Arguments
- •Argument-Passing Mechanisms
- •Event-Handler Arguments
- •Passing an Unknown Number of Arguments
- •Named Arguments
- •More Types of Function Return Values
- •Overloading Functions
- •Summary
- •The Appearance of Forms
- •Properties of the Form Control
- •Placing Controls on Forms
- •Setting the TabOrder
- •VB.NET at Work: The Contacts Project
- •Anchoring and Docking
- •Loading and Showing Forms
- •The Startup Form
- •Controlling One Form from within Another
- •Forms vs. Dialog Boxes
- •VB.NET at Work: The MultipleForms Project
- •Designing Menus
- •The Menu Editor
- •Manipulating Menus at Runtime
- •Building Dynamic Forms at Runtime
- •The Form.Controls Collection
- •VB.NET at Work: The DynamicForm Project
- •Creating Event Handlers at Runtime
- •Summary
- •The TextBox Control
- •Basic Properties
- •Text-Manipulation Properties
- •Text-Selection Properties
- •Text-Selection Methods
- •Undoing Edits
- •VB.NET at Work: The TextPad Project
- •Capturing Keystrokes
- •The ListBox, CheckedListBox, and ComboBox Controls
- •Basic Properties
- •The Items Collection
- •VB.NET at Work: The ListDemo Project
- •Searching
- •The ComboBox Control
- •The ScrollBar and TrackBar Controls
- •The ScrollBar Control
- •The TrackBar Control
- •Summary
- •The Common Dialog Controls
- •Using the Common Dialog Controls
- •The Color Dialog Box
- •The Font Dialog Box
- •The Open and Save As Dialog Boxes
- •The Print Dialog Box
- •The RichTextBox Control
- •The RTF Language
- •Methods
- •Advanced Editing Features
- •Cutting and Pasting
- •Searching in a RichTextBox Control
- •Formatting URLs
- •VB.NET at Work: The RTFPad Project
- •Summary
- •What Is a Class?
- •Building the Minimal Class
- •Adding Code to the Minimal Class
- •Property Procedures
- •Customizing Default Members
- •Custom Enumerations
- •Using the SimpleClass in Other Projects
- •Firing Events
- •Shared Properties
- •Parsing a Filename String
- •Reusing the StringTools Class
- •Encapsulation and Abstraction
- •Inheritance
- •Inheriting Existing Classes
- •Polymorphism
- •The Shape Class
- •Object Constructors and Destructors
- •Instance and Shared Methods
- •Who Can Inherit What?
- •Parent Class Keywords
- •Derived Class Keyword
- •Parent Class Member Keywords
- •Derived Class Member Keyword
- •MyBase and MyClass
- •Summary
- •On Designing Windows Controls
- •Enhancing Existing Controls
- •Building the FocusedTextBox Control
- •Building Compound Controls
- •VB.NET at Work: The ColorEdit Control
- •VB.NET at Work: The Label3D Control
- •Raising Events
- •Using the Custom Control in Other Projects
- •VB.NET at Work: The Alarm Control
- •Designing Irregularly Shaped Controls
- •Designing Owner-Drawn Menus
- •Designing Owner-Drawn ListBox Controls
- •Using ActiveX Controls
- •Summary
- •Programming Word
- •Objects That Represent Text
- •The Documents Collection and the Document Object
- •Spell-Checking Documents
- •Programming Excel
- •The Worksheets Collection and the Worksheet Object
- •The Range Object
- •Using Excel as a Math Parser
- •Programming Outlook
- •Retrieving Information
- •Recursive Scanning of the Contacts Folder
- •Summary
- •Advanced Array Topics
- •Sorting Arrays
- •Searching Arrays
- •Other Array Operations
- •Array Limitations
- •The ArrayList Collection
- •Creating an ArrayList
- •Adding and Removing Items
- •The HashTable Collection
- •VB.NET at Work: The WordFrequencies Project
- •The SortedList Class
- •The IEnumerator and IComparer Interfaces
- •Enumerating Collections
- •Custom Sorting
- •Custom Sorting of a SortedList
- •The Serialization Class
- •Serializing Individual Objects
- •Serializing a Collection
- •Deserializing Objects
- •Summary
- •Handling Strings and Characters
- •The Char Class
- •The String Class
- •The StringBuilder Class
- •VB.NET at Work: The StringReversal Project
- •VB.NET at Work: The CountWords Project
- •Handling Dates
- •The DateTime Class
- •The TimeSpan Class
- •VB.NET at Work: Timing Operations
- •Summary
- •Accessing Folders and Files
- •The Directory Class
- •The File Class
- •The DirectoryInfo Class
- •The FileInfo Class
- •The Path Class
- •VB.NET at Work: The CustomExplorer Project
- •Accessing Files
- •The FileStream Object
- •The StreamWriter Object
- •The StreamReader Object
- •Sending Data to a File
- •The BinaryWriter Object
- •The BinaryReader Object
- •VB.NET at Work: The RecordSave Project
- •The FileSystemWatcher Component
- •Properties
- •Events
- •VB.NET at Work: The FileSystemWatcher Project
- •Summary
- •Displaying Images
- •The Image Object
- •Exchanging Images through the Clipboard
- •Drawing with GDI+
- •The Basic Drawing Objects
- •Drawing Shapes
- •Drawing Methods
- •Gradients
- •Coordinate Transformations
- •Specifying Transformations
- •VB.NET at Work: Plotting Functions
- •Bitmaps
- •Specifying Colors
- •Defining Colors
- •Processing Bitmaps
- •Summary
- •The Printing Objects
- •PrintDocument
- •PrintDialog
- •PageSetupDialog
- •PrintPreviewDialog
- •PrintPreviewControl
- •Printer and Page Properties
- •Page Geometry
- •Printing Examples
- •Printing Tabular Data
- •Printing Plain Text
- •Printing Bitmaps
- •Using the PrintPreviewControl
- •Summary
- •Examining the Advanced Controls
- •How Tree Structures Work
- •The ImageList Control
- •The TreeView Control
- •Adding New Items at Design Time
- •Adding New Items at Runtime
- •Assigning Images to Nodes
- •Scanning the TreeView Control
- •The ListView Control
- •The Columns Collection
- •The ListItem Object
- •The Items Collection
- •The SubItems Collection
- •Summary
- •Types of Errors
- •Design-Time Errors
- •Runtime Errors
- •Logic Errors
- •Exceptions and Structured Exception Handling
- •Studying an Exception
- •Getting a Handle on this Exception
- •Finally (!)
- •Customizing Exception Handling
- •Throwing Your Own Exceptions
- •Debugging
- •Breakpoints
- •Stepping Through
- •The Local and Watch Windows
- •Summary
- •Basic Concepts
- •Recursion in Real Life
- •A Simple Example
- •Recursion by Mistake
- •Scanning Folders Recursively
- •Describing a Recursive Procedure
- •Translating the Description to Code
- •The Stack Mechanism
- •Stack Defined
- •Recursive Programming and the Stack
- •Passing Arguments through the Stack
- •Special Issues in Recursive Programming
- •Knowing When to Use Recursive Programming
- •Summary
- •MDI Applications: The Basics
- •Building an MDI Application
- •Built-In Capabilities of MDI Applications
- •Accessing Child Forms
- •Ending an MDI Application
- •A Scrollable PictureBox
- •Summary
- •What Is a Database?
- •Relational Databases
- •Exploring the Northwind Database
- •Exploring the Pubs Database
- •Understanding Relations
- •The Server Explorer
- •Working with Tables
- •Relationships, Indices, and Constraints
- •Structured Query Language
- •Executing SQL Statements
- •Selection Queries
- •Calculated Fields
- •SQL Joins
- •Action Queries
- •The Query Builder
- •The Query Builder Interface
- •SQL at Work: Calculating Sums
- •SQL at Work: Counting Rows
- •Limiting the Selection
- •Parameterized Queries
- •Calculated Columns
- •Specifying Left, Right, and Inner Joins
- •Stored Procedures
- •Summary
- •How About XML?
- •Creating a DataSet
- •The DataGrid Control
- •Data Binding
- •VB.NET at Work: The ViewEditCustomers Project
- •Binding Complex Controls
- •Programming the DataAdapter Object
- •The Command Objects
- •The Command and DataReader Objects
- •VB.NET at Work: The DataReader Project
- •VB.NET at Work: The StoredProcedure Project
- •Summary
- •The Structure of a DataSet
- •Navigating the Tables of a DataSet
- •Updating DataSets
- •The DataForm Wizard
- •Handling Identity Fields
- •Transactions
- •Performing Update Operations
- •Updating Tables Manually
- •Building and Using Custom DataSets
- •Summary
- •An HTML Primer
- •HTML Code Elements
- •Server-Client Interaction
- •The Structure of HTML Documents
- •URLs and Hyperlinks
- •The Basic HTML Tags
- •Inserting Graphics
- •Tables
- •Forms and Controls
- •Processing Requests on the Server
- •Building a Web Application
- •Interacting with a Web Application
- •Maintaining State
- •The Web Controls
- •The ASP.NET Objects
- •The Page Object
- •The Response Object
- •The Request Object
- •The Server Object
- •Using Cookies
- •Handling Multiple Forms in Web Applications
- •Summary
- •The Data-Bound Web Controls
- •Simple Data Binding
- •Binding to DataSets
- •Is It a Grid, or a Table?
- •Getting Orders on the Web
- •The Forms of the ProductSearch Application
- •Paging Large DataSets
- •Customizing the Appearance of the DataGrid Control
- •Programming the Select Button
- •Summary
- •How to Serve the Web
- •Building a Web Service
- •Consuming the Web Service
- •Maintaining State in Web Services
- •A Data-Driven Web Service
- •Consuming the Products Web Service in VB
- •Summary
896 Chapter 20 DATABASES: ARCHITECTURE AND BASIC CONCEPTS
Null Values
A very common operation in manipulating and maintaining databases is to locate Null values in fields. The expressions IS NULL and IS NOT NULL find field values that are (or are not) Null. A zero-length string is not the same as a Null field. To locate the rows which have a Null value in their CompanyName column, use the following WHERE clause:
WHERE CompanyName IS NULL
A Null price in the Products table means that the product’s price was not available at the time of the data entry. You can easily locate the products without prices and edit them. The following statement will locate products without prices:
USE NORTHWIND
SELECT * FROM Products WHERE UnitPrice IS NULL
Certain fields can’t be Null in a table. The primary key, for example, can’t be Null. It also doesn’t make sense to enter a new customer without a name, or a book without a title. When you design the database, you can request that certain columns can’t be Null; the DBMS will ensure that no row with a Null value in these columns will be added to the table.
ORDER Keyword
The rows of a query are not in any particular order. To request that the rows be returned in a specific order, use the ORDER BY clause, whose syntax is
ORDER BY col1, col2, . . .
You can specify any number of columns in the ORDER list. The output of the query is ordered according to the values of the first column (col1). If two rows have identical values in this column, then they are sorted according to the second column, and so on. The statement
USE NORTHWIND
SELECT CompanyName, ContactName
FROM Customers
ORDER BY Country, City
will display the customers ordered by country and by city within each country.
Calculated Fields
In addition to column names, you can specify calculated columns in the SELECT statement. The Order Details table contains a row for each invoice line. Invoice #10248, for instance, contains four lines (four items sold), and each detail line appears in a separate row in the Order Details table. Each row holds the number of items sold, the item’s price, and the corresponding discount. To display the line’s subtotal, you must multiply the quantity by the price minus the discount, as shown in the following statement:
USE NORTHWIND
SELECT Orders.OrderID, ProductID,
|
[Order Details].UnitPrice * [Order Details].Quantity * |
|
(1 - [Order Details].Discount) AS SubTotal |
FROM |
Orders, [Order Details] |
WHERE |
Orders.OrderID = [Order Details].OrderID |
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
STRUCTURED QUERY LANGUAGE 897
This statement will calculate the subtotal for each line in the invoices issued to all Northwind customers and display them along with the order number, as shown in Figure 20.14. The order numbers are repeated as many times as there are products in the order (or lines in the invoice). In the following section, “Totaling and Counting,” you will find out how to calculate totals, too.
Figure 20.14
Calculating the subtotals for each item sold
Note Long lines in a SQL statement can be broken anywhere, and there’s no need to insert a line-continuation character, as you do with VB statements.
Tip You can shorten the preceding SQL statement by omitting the table name qualifier for the ProductID, Quantity, and UnitPrice fields, since their names do not appear in any other table. You can’t omit the table qualifier from the OrderID field’s name, because it appears in both tables involved in the query.
Totaling and Counting
SQL supports some aggregate functions, which act on selected fields of all the rows returned by the query. The aggregate functions, listed in Table 20.2, perform basic calculations like summing, counting, and averaging numeric values. Aggregate functions accept field names (or calculated fields) as arguments, and they return a single value, which is the sum (or average) of all values.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
898 Chapter 20 DATABASES: ARCHITECTURE AND BASIC CONCEPTS
Table 20.2: SQL’s Aggregate Functions
Function |
Returns |
COUNT() |
The number (count) of values in a specified column |
SUM() |
The sum of values in a specified column |
AVG() |
The average of the values in a specified column |
MIN() |
The smallest value in a specified column |
MAX() |
The largest value in a specified column |
|
|
These functions operate on a single column (which could be a calculated column) and return a single value. The rows involved in the calculations are specified with the proper WHERE clause. The SUM() and AVG() functions can process only numeric values. The other three functions can process both numeric and text values.
These functions are used to summarize data from one or more tables. Let’s say we want to know how many of the Northwind database customers are located in Germany. The following SQL statement will return the desired value:
USE NORTHWIND
SELECT COUNT(CustomerID)
FROM Customers
WHERE Country = ‘Germany’
This is a simple demonstration of the COUNT() function. If you want to count unique values, you must use the DISTINCT keyword along with the name of the field to count. If you want to find out in how many countries there are Northwind customers, use the following SQL statement:
USE NORTHWIND
SELECT COUNT(DISTINCT Country)
FROM Customers
If you omit the DISTINCT keyword, the statement will return the number of rows that have a Country field. The aggregate functions ignores the Null values, unless you specify the * argument. The following statement will return the count of all rows in the Customers table, even if some of them have a Null in the Country column:
USE NORTHWIND
SELECT COUNT(*)
FROM Customers
The SUM() function is used to total the values of a specific field in the specified rows. To find out how many units of the product with ID = 11 (Queso Cabrales) have been sold, use the following statement:
USE NORTHWIND
SELECT SUM(Quantity)
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
STRUCTURED QUERY LANGUAGE 899
FROM [Order Details]
WHERE ProductID = 11
The SQL statement that returns the total revenue generated by a single product is a bit more complicated. To calculate it, you must add the products of quantities times prices, taking into consideration each invoice’s discount:
USE NORTHWIND
SELECT SUM(Quantity * UnitPrice * (1 - Discount))
FROM [Order Details]
WHERE ProductID = 11
You will find out that Queso Cabrales generated a total revenue of $12,901.77. If you want to know how many items of this product were sold, add one more aggregate function to the query to sum the quantities of each row that refers to the specific product ID:
USE NORTHWIND
SELECT SUM(Quantity),
SUM(Quantity * UnitPrice * (1 - Discount))
FROM [Order Details]
WHERE ProductID = 11
SQL Joins
Joins specify how you connect multiple tables in a query, and there are four types of joins:
Left outer, or left join
Right outer, or right join
Full outer, or full join
Inner join
A join operation combines all the rows of one table with the rows of another table. Joins are usually followed by a condition, which determines which records in either side of the join will appear in the result. The WHERE clause of the SELECT statement is very similar to a join, but there some fine points that will be explained momentarily.
Note The left, right, and full joins are sometimes called “outer” joins to differentiate them from an inner join. “Left join” and “left outer join” mean the same thing.
Left Joins
This join displays all the records in the left table and only those records of the table on the right that match certain user-supplied criteria. This join has the following syntax:
FROM (primary table) LEFT JOIN (secondary table) ON (primary table).(field) (comparison) (secondary table).(field)
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
900 Chapter 20 DATABASES: ARCHITECTURE AND BASIC CONCEPTS
The left outer join retrieves all rows in the primary table and the matching rows from a secondary table. The following statement will retrieve all the titles from the Pubs database along with their publisher. If some titles have no publisher, they will be included to the result:
USE PUBS
SELECT |
title, pub_name |
FROM |
titles LEFT JOIN publishers |
|
ON titles.pub_id = publishers.pub_id |
Right Joins
This join is similar to the left outer join, except that all rows in the table on the right are displayed and only the matching rows from the left table are displayed. This join has the following syntax:
FROM (secondary table) RIGHT JOIN (primary table) ON (secondary table).(field) (comparison) (primary table).(field)
The following statement retrieves all the publishers from the Pubs database along with their titles. Notice that this statement is almost exactly the same as the example of the left outer join entry; I only changed LEFT to RIGHT:
USE PUBS
SELECT |
title, pub_name |
FROM |
titles RIGHT JOIN publishers |
|
ON titles.pub_id = publishers.pub_id |
Full Joins
The full join returns all the rows of the two tables, regardless of whether there are matching rows or not. In effect, it’s a combination of left and right joins. To retrieve all the titles and all publishers, and match publishers to their titles, use the following join:
USE PUBS
SELECT |
title, pub_name |
FROM |
titles FULL JOIN publishers |
|
ON titles.pub_id = publishers.pub_id |
Inner Joins
This join returns the matching rows of both tables, similar to the WHERE clause, and has the following syntax:
FROM (primary table) INNER JOIN (secondary table) ON (primary table).(field) (comparison) (secondary table).(field)
The following SQL statement combines records from the Titles and Publishers tables of the PUBS database if their PubID fields match. It returns all the titles and their publishers. Titles without publishers will not be included in the result:
USE PUBS
SELECT titles.title, publishers.pub_name FROM titles, publishers
WHERE titles.pub_id = publishers.pub_id
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
STRUCTURED QUERY LANGUAGE 901
You can retrieve the same rows using an inner join, as follows:
USE PUBS
SELECT titles.title, publishers.pub_name
FROM titles INNER JOIN publishers ON titles.pub_id = publishers.pub_id
For more examples with joins, see the section “Specifying Left, Right, and Inner Joins,” later in this chapter.
Grouping Rows
Sometimes you need to group the results of a query, so that you can calculate subtotals. Let’s say you need not only the total revenues generated by a single product, but a list of all products and the revenues they generated. The example of the previous section “Totaling and Counting” calculates the total revenue generated by a single product. If you omit the WHERE clause, it will calculate the total revenue generated by all products. It is possible to use the SUM() function to break the calculations at each new product ID as demonstrated in the following statement. To do so, you must group the product IDs together with the GROUP BY clause.
USE NORTHWIND
SELECT |
ProductID, |
|
SUM(Quantity * UnitPrice *(1 - Discount)) AS [Total Revenues] |
FROM |
[Order Details] |
GROUP BY ProductID
ORDER BY ProductID
The above statement will produce an output like this one:
ProductID Total Revenues
112788.10
216355.96
33044.0
48567.89
55347.20
67137.0
722044.29
As you can see, the SUM() function works in tandem with the GROUP BY clause (when there is one) to produce subtotals. The GROUP BY clause groups all the rows with the same values in the specified column and forces the aggregate functions to act on each group separately. SQL Server will sort the rows according to the column specified in the GROUP BY clause and start calculating the aggregate functions. Every time it runs into a new group, it prints the result and resets the aggregate function(s).
If you use the GROUP BY clause in a SQL statement, you must be aware of the following rule:
All the fields included in the SELECT list must be either part of an aggregate function or part of the GROUP BY clause.
Let’s say you want to change the previous statement to display the names of the products, rather than their IDs. The following statement will display product names, instead of product IDs. Notice
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
902 Chapter 20 DATABASES: ARCHITECTURE AND BASIC CONCEPTS
that the ProductName field doesn’t appear as an argument to an aggregate function, so it must be part of the GROUP BY clause.
USE NORTHWIND
SELECT |
ProductName, |
|
SUM(Quantity * [Order Details].UnitPrice * (1 - Discount)) |
|
AS [Total Revenues] |
FROM |
[Order Details], Products |
WHERE |
Products.ProductID = [Order Details].ProductID |
GROUP BY ProductName
ORDER BY ProductName
These are the first few lines of the output produced by this statement:
ProductName |
Total Revenues |
Alice Mutton |
32698.38 |
Aniseed Syrup |
3044.0 |
Boston Crab Meat |
17910.63 |
Camembert Pierrot |
46927.48 |
Carnarvon Tigers |
29171.87 |
If you omit the GROUP BY clause, the query will return the total revenue generated by all the products in the database.
You can also combine multiple aggregate functions in the SELECT field. The following statement will calculate the units of products sold, along with the revenue they generated and the number of invoices that contain the specific product:
USE NORTHWIND
SELECT |
ProductID AS PRODUCT, |
|
COUNT(ProductID) AS [INVOICES], |
|
SUM(Quantity) AS [UNITS SOLD], |
|
SUM(Quantity * UnitPrice *(1 - Discount)) AS Revenue |
FROM |
[Order Details] |
GROUP BY ProductID
ORDER BY ProductID
The following SELECT statement returns all product IDs along with the number of invoices that contain them, and the minimum, maximum, and average quantity ordered:
USE NORTHWIND
SELECT |
ProductID AS PRODUCT, |
|
COUNT(ProductID) AS [Invoices], |
|
MIN(Quantity) AS [Min], |
|
MAX(Quantity) AS [Max], |
|
AVG(Quantity) AS [Average] |
FROM |
[Order Details] |
GROUP BY ProductID
ORDER BY ProductID
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
STRUCTURED QUERY LANGUAGE 903
Limiting Groups with HAVING
The HAVING clause limits the groups that will appear in the cursor. In a way, it is similar to the WHERE clause, but the HAVING clause allows you to use aggregate functions. The following statement will return the IDs of the products whose sales exceed 1,000 units:
USE NORTHWIND
SELECT ProductID, SUM(Quantity)
FROM [Order Details]
GROUP BY ProductID
HAVING SUM(Quantity) > 1000
If you want to include regular restrictions, you can use the WHERE clause as well. To see product names instead of IDs, add a slightly longer statement that includes the Products table and maps them to the ProductIDs in the Order Details table with a WHERE clause:
USE NORTHWIND
SELECT |
Products.ProductName, |
|
[Order Details].ProductID, |
|
SUM(Quantity) AS [Items Sold] |
FROM |
Products, [Order Details] |
WHERE |
[Order Details].ProductID = Products.ProductID |
GROUP BY |
[Order Details].ProductID, Products.ProductName |
HAVING |
SUM(Quantity) > 1000 |
ORDER BY |
Products.ProductName |
IN and NOT IN Keywords
The IN and NOT IN keywords are used in a WHERE clause to specify a list of values that a column must match (or not match). They are more of a shorthand notation for multiple OR operators. The following is statement that retrieves the names of the customers in all German-speaking countries:
USE NORTHWIND
SELECT CompanyName
FROM Customers
WHERE Country IN (‘Germany’, ‘Austria’, ‘Switzerland’)
The BETWEEN Keyword
The BETWEEN keyword lets you specify a range of values and limit the selection to the rows that have a specific column in this range. The BETWEEN keyword is a shorthand notation for an expression like
column >= minValue AND column <= maxValue
To retrieve the orders placed in 1997, use the following statement:
USE NORTHWIND
SELECT OrderID, OrderDate, CompanyName
FROM Orders, Customers
WHERE Orders.CustomerID = Customers.CustomerID AND
(OrderDate BETWEEN ‘1/1/1997’ AND ‘1/1/1998’)
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
