Specialized IT Services focused on Data Management | Speak with Us 877-634-9222
Limiting the Number of Rows Fetched
Application developers frequently need to retrieve a limited number of qualifying rows from a table. For example, maybe you need to list the top ten bestselling items from inventory, or a list of the top five most expensive products (i.e., highest price tag). There are several ways to accomplish this prior to DB2 V7 using SQL, but they are not necessarily efficient.
The first reaction is to simply use the WHERE clause to eliminate non-qualifying rows. But this is simplistic, and often is not sufficient to produce the results desired in an optimal manner. What if the program only requires that the top ten results be returned? This can be a somewhat difficult request to formulate using SQL alone.
Consider, for example, an application that needs to retrieve only the top ten most highly paid employees from the EMP sample table. You could simply issue a SQL request that retrieves all of the employees in order by salary, but only use the first ten retrieved. That is easy; for example:
EMPNO, FIRSTNME, LASTNAME, SALARY
ORDER BY SALARY DESC;
You must specify the ORDER BY clause with the DESC key word. This sorts the results into descending order, instead of the default, which is ascending. Without the DESC key word, the “top ten” would be at the very end of the results set, not at the beginning.
But that does not really satisfy the requirement – retrieving only the top ten? It merely sorts the results into descending sequence. So, the results would still be all employees in the table, but in the correct order so you can view the “top ten” salaries very easily. The ideal solution should return only the top ten employees with the highest salary and not merely a sorted list of all employees.
You can code some “tricky” SQL to support this request for all versions of DB2, such as the following:
SELECT EMPNO, FIRSTNME, LASTNAME, SALARY
FROM DSN8710.EMP A
WHERE 10 > (SELECT COUNT(*)
FROM DSN8710.EMP B
WHERE A.SALARY < B.SALARY)
AND SALARY IS NOT NULL
ORDER BY SALARY DESC;
This SQL is portable from DB2 to other DBMSs, such as Oracle or SQL Server. And, of course, you can change the constant 10 to any number you wish, thereby retrieving the top 20, or top 5, as deemed necessary by the needs of your application.
Since the SALARY column is nullable in the EMP table, you must remove the nulls from the results set. And the ORDER BY is required to sort the results in the right order. If it is removed from the query, the results will still contain the top ten, but they will be in no particular order.
But DB2, as of V7, provides an easier and less complicated way to limit the results of a SELECT statement – the FIRST key word. You can code FETCH FIRST n ROWS which will limit the number of rows that are fetched and returned by a SELECT statement.
Additionally, you can specify a new clause — FETCH FIRST ROW ONLY clause — on SELECT INTO statements when the query can return more than one row in the answer set. Doing so informs DB2 to ignore the other rows.
There is one difference between the new V7 formulation and the other SELECT statement we reviewed, and that is the way “ties” are handled. A tie occurs when more than one row contains the same value. The previous query we examined may return more than 10 rows if there are multiple rows with the same value for price within the top ten.
Using the FIRST key word DB2 will limit the number of rows returned to ten, even if there are other rows with the same value for price as the number ten row in the results set. The needs of your application will dictate whether ties are to be ignored or included in the result set. If all “ties” need to be included in the results set, which would mean that more than 10 rows would be needed, the new V7 feature may not prove to be helpful.
And it is also important to note that as of DB2 9, you can include the FETCH FIRST clause in a subselect. ORDER BY is allowed in a subselect, too. The subselect MUST be enclosed in parentheses and the FETCH FIRST (or ORDER BY) cannot be in the outermost fullselect of a view, or in a materialized query table.
This post was originally published on Craig Mullins’ blog at: http://db2portal.blogspot.com/2009/09/limiting-number-of-rows-fetched.html
For additional resources please download my white paper: “The Many Different Types of DBAs.”