About Creating Queries

A query requests data from the database. At its simplest, a query merely fetches all data from a single table. But as you create more complex (and more typical) queries, you can assemble exactly the data you want in the following ways:

Including or excluding rows

Using search conditions

To restrict the number of rows a query should return, you create search conditions or filter criteria. In SQL, search conditions appear in the WHERE clause of the statement, or if you are creating an aggregate query, in the HAVING clause.

Note   You can also use search conditions to indicate which rows are affected by an Update, Update Values, Delete, or Make-Table query.

When the query runs, the database engine examines and applies the search condition to each row in the tables you are searching. If the row meets the condition, it is included in the query. For example, a search condition that would find all the employees in a particular region might be:

region = 'UK'

To establish the criteria for including a row in a result, you can use multiple search conditions. For example, the following search criterion consists of two search conditions. The query includes a row in the result set only if that row satisfies both of the conditions.

region = 'UK' AND product_line = 'Housewares'

You can combine these conditions with AND or OR. The previous example uses AND. In contrast, the following criterion uses OR. The attendant query result will include any row that satisfies either or both of the search conditions:

region = 'UK' OR product_line = 'Housewares'

You can even combine search conditions on a single column. For example, the following criterion combines two conditions on the region column:

region = 'UK' OR region = 'US'

Predicates in search conditions

A search condition consists of one or more predicates, each specifying a single condition. If the search condition includes more than one predicate, the predicates are linked with a logical AND (to narrow the search) or OR (to broaden it). The following example shows how you can use multiple conditions when searching an employee table to find the employee (or employees) with the specified first and last names:

WHERE lname = 'Smith' AND fname = 'Jean'

A single predicate follows this format:

search_expression operator search_value

In most instances, search_expression is the name of a column to search. Similarly, the most common form of search_value is a literal value to search for, which can be either a string of characters or a number.

The following two examples show literal values. The first searches for all the employees who are in the United Kingdom, and the second searches for all employees with a specific job level:

WHERE region = 'UK'

WHERE job_lvl = 100

Both search_expression and search_value can consist of any (or any combination) of the following:

Including or excluding columns

You can choose which columns appear in a query result. When choosing which columns to include, there are several things to keep in mind:

Combining tables

A query result can include data from multiple tables. To combine data from tables, you use the Join operation from SQL.

The basic join operation

The Join operation matches rows of one table with rows of another table, based on values in those rows. For example, you can join the table titles with the table publishers. Each row in the result set will describe a title, including information about that titleÆs publisher, as shown in the following illustration:

Types of joins

When you join tables, the type of join that you create affects the rows that appear in the result set. You can create the following types of joins:

Joining columns

The JOIN operator matches rows by comparing values in one table with values in another. You decide which columns from each table should be matched. You have several choices:

Note also that you use multiple columns to match rows from the joined tables. For example, to find the author-publisher pairs in which the author and publisher are located in the same city, you use a join operation matching the respective state columns and the respective city columns of the two tables. You need to match both city and state because it is possible that different states could have like-named cities (e.g., Springfield, Illinois and Springfield, Massachusetts).

Join comparison operators

The JOIN operator matches rows by comparing values in one table with values in another. You can decide exactly what constitutes a match. Your choices fall into two broad categories:

Joining tables

When combining data from multiple tables, you must decide what tables to use. There are several noteworthy considerations:

 

Collapsing groups of rows

You can create a query result in which each result row corresponds to an entire group of rows from the original data. When collapsing rows, there are several things to keep in mind:

Using a table twice in one query

You can use the same table two (or more) times within a single query. There are several situations in which you do this.

Using views, user-defined functions, and subqueries in place of a table

Whenever you write a query, you articulate what columns you want, what rows you want, and where the query processor should find the original data. Typically, this original data consists of a table or several tables joined together. But the original data can come from sources other than tables. In fact, it can come from views, user-defined functions that return a table, or subqueries.

Using a view in place of a table

You can select rows from a view. For example, suppose the database includes a view called ôExpensiveBooks,ö in which each row describes a title whose price exceeds 19.99. The view definition might look like this:

SELECT *
FROM titles
WHERE price > 19.99

You can select the expensive psychology books merely by selecting the psychology books from the ExpensiveBooks view. The resulting SQL might look like this:

SELECT *
FROM ExpensiveBooks
WHERE type = 'psychology'

Similarly, a view can participate in a JOIN operation. For example, you can find the sales of expensive books merely by joining the sales table to the ExpensiveBooks view. The resulting SQL might look like this:

SELECT *
FROM sales 
 INNER JOIN 
 ExpensiveBooks 
 ON sales.title_id 
 = ExpensiveBooks.title_id

Using a user-defined function in place of a table

In Microsoft SQL Server 2000 or higher, you can create a user-defined function that returns a table. Such functions are useful for performing complex or procedural logic.

For example, suppose the employee table contains an additional column, employee.manager_emp_id, and that a foreign key exists from manager_emp_id to employee.emp_id. Within each row of the employee table, the manager_emp_id column indicates the employeeÆs boss. More precisely, it indicates the employeeÆs bossÆs emp_id. You can create a user-defined function that returns a table containing one row for each employee working within a particular high-level managerÆs organizational hierarchy. You might call the function fn_GetWholeTeam, and design it to take an input variable ù the emp_id of the manager whose team you want to retrieve.

You can write a query that uses the fn_GetWholeTeam function as a source of data. The resulting SQL might look like this:

SELECT * 
FROM 
 fn_GetWholeTeam ('VPA30890F')

ôVPA30890Fö is the emp_id of the manager whose organization you want to retrieve.

Using a subquery in place of a table

You can select rows from a subquery. For example, suppose you have already written a query retrieving titles and identifiers of the coauthored books ù the books with more than one author. The SQL might look like this:

SELECT 
 titles.title_id, title, type
FROM 
 titleauthor 
 INNER JOIN
 titles 
 ON titleauthor.title_id 
 = titles.title_id 
GROUP BY 
 titles.title_id, title, type
HAVING COUNT(*) > 1

You can then write another query that builds on this result. For example, you can write a query that retrieves the coauthored psychology books. To write this new query, you can use the existing query as the source of the new queryÆs data. The resulting SQL might look like this:

SELECT 
 title
FROM 
 (
 SELECT 
 titles.title_id, 
 title, 
 type
 FROM 
 titleauthor 
 INNER JOIN
 titles 
 ON titleauthor.title_id 
 = titles.title_id 
 GROUP BY 
 titles.title_id, 
 title, 
 type
 HAVING COUNT(*) > 1
 ) 
 co_authored_books
WHERE type = 'psychology'

The emphasized text shows the existing query used as the source of the new queryÆs data. Note that the new query uses an alias (ôco_authored_booksö) for the existing query.

Similarly, a query can participate in a JOIN operation. For example, you can find the sales of expensive coauthored books merely by joining the ExpensiveBooks view to the query retrieving the coauthored books. The resulting SQL might look like this:

SELECT 
 ExpensiveBooks.title
FROM 
 ExpensiveBooks 
 INNER JOIN
  (
 SELECT 
 titles.title_id, 
 title, 
 type
 FROM 
 titleauthor 
 INNER JOIN
 titles 
 ON titleauthor.title_id 
 = titles.title_id 
 GROUP BY 
 titles.title_id, 
 title, 
 type
 HAVING COUNT(*) > 1
 )

Sorting rows

You can order the rows in a query result. That is, you can name a particular column or set of columns whose values determine the order of rows in the result set. There are several ways in which you can use ordering: