Previous | Table of Contents | Next |
Note that with COMPUTE and COMPUTE BY, the rowcount reported by the server includes the computed row, but doesnt include extra rows for the === lines or the name of the aggregate.
You can use COMPUTE BY and COMPUTE together to create subtotal and total information. Ill use the same query as before, but this time I will add a COMPUTE clause to the very end, in order to get the maximum advance for all books. (Ill leave out the rows in the middle for the sake of simplicity.)
select title_id, type, advance from titles order by type compute max(advance) by type compute max(advance)
title_id type advance -------- ------------ -------------------------- MC3026 UNDECIDED (null) max ========================== (null) [ ] title_id type advance -------- ------------ -------------------------- TC3218 trad_cook 7,000.00 TC4203 trad_cook 4,000.00 TC7777 trad_cook 8,000.00 max ========================== 8,000.00 max ========================== 15,000.00
Multiple COMPUTE BY Clauses
If you list multiple columns in the COMPUTE BY clause, all of them must appear in the ORDER BY. Additionally, the order by which the columns are sorted is important. Suppose you have a table with columns price, c1, c2, c3, c4, and c5, and you write a query like this:
select c1, c2, c3, c4, c5, price from t1 order by c1, c2, c3
Assuming you want to calculate a SUM of these columns, the only choices you have for the COMPUTE BY clause are
compute sum(price) by c1 compute sum(price) by c1, c2 compute sum(price) by c1, c2, c3
This is because the rows are first placed into a worktable and then the server works its way through that table to add the computed results. If all like rows are not listed sequentially (by using the ORDER BY), the COMPUTE wont know on which rows to operate.
Compute is different from other clauses in a lot of ways:
These differences, especially the first, have caused COMPUTE to fall out of favor with most users. In application programs, it is common to see aggregate results generated by the client, by reading each value and computing the SUM, AVG, MIN, MAX, or COUNT without asking for a computed result. The only time COMPUTE sees real use these days is by ad-hoc users with access to ISQL/w or another query tool, and in legacy SQL code.
Technical Note: How applications benefit from aggregates
Some client programs calculate aggregates on their own, simply by asking for all the rows from the server and handling the math once the values are retrieved. This approach is fine when the normal rows are used in the client program in addition to the aggregates.If all you want is an aggregate, however, its much more efficient for the server to do the work, especially with respect to network bandwidth.
The HAVING clause allows you to restrict rows that are returned, without restricting the rows that take part in the calculation of those rows. HAVING can be used only with GROUP BY to filter out aggregate results.
In previous versions of the server that did not maintain strict ANSI compliance, HAVING would function like the WHERE clause when used with GROUP BY. Some users exclusively used HAVING to evaluate all conditions, which led to horrible performance. If you see legacy code such as this, you can chuckle to yourself, knowing that the original author didnt understand the difference between HAVING and WHERE, as you do.
Now, lets take a look at a HAVING example. To see all book types with average prices over $12, use this query:
select type, avg(price) from titles group by type having avg(price) > $12
type ------------ -------------------------- business 13.73 popular_comp 21.48 psychology 13.50 trad_cook 15.96
This query starts out the same way the other queries in this chapter do: they calculate the average prices of each type of book in the titles table. Once that result set is complete, but before returning the results, the HAVING clause is evaluated. The results are searched, and any type of book with an average price greater than $12 is returned. Although modern cookbooks are initially included in the intermediate result set, the HAVING clause culls out this type.
In a query including WHERE, HAVING, GROUP BY, and COMPUTE, here is how the server evaluates the three clauses:
Here is the syntax for the SQL SELECT, incorporating all elements that you have learned to date:
SELECT [DISTINCT] <column | constant>[, <column | constant> ] FROM <table list> WHERE <Boolean condition> [<AND | OR> <Boolean condition> ] GROUP BY <Column list> [WITH <CUBE | ROLLUP>] HAVING <Boolean condition> [<AND | OR> <B oolean condition> ] ORDER BY <column name> | <ordinal column position> } <column alias> [, <name>, <ordinal>, <alias> ] COMPUTE<aggregate> BY <Ordered column> [, <agg> BY <orderedcol> ] COMPUTE<aggregate>
Previous | Table of Contents | Next |