Here's a tip for limiting the number of rows returned from a query. Now I know you think "that's easy - just use TOP." Ah... but what if TOP is not an option? Consider this example. You have a reporting stored procedure that you want to use to return multiple results sets to your Coldfusion Page. Easy - right?
First, here is our simple procedure.
<cfquery>
CREATE PROCEDURE [dbo].[myReport]
WITH RECOMPILE AS
SET NOCOUNT ON
SELECT count(s.saleID) AS total, a.AuthorName
FROM authors a JOIN sales s ON
a.author_id = s.author_ID
GROUP BY a.AuthorName
ORDER BY total desc
SELECT sum(s.prive) AS totalRevenue, s.Title
FROM sales
GROUP BY s.Title
ORDER BY totalRevenue desc
SET NOCOUNT OFF
</cfquery>
Notice I've left off some boiler plate for quoted_identifiers and ansi_nulls. This Stored Procedure returns 2 results sets. The first grabs the total number of books sold and totals them by author with the best selling authors first. The second totals the revenue per book and returns the highest revenue books first. To call this SP you will need code like this:
<cfstoredproc datasource="myDSN" procedure="myReport">
<cfprocresult name="Authors" resultset="1">
<cfprocresult name="Revenue" resultset="2">
</cfstoredproc>
When we run this code we end up with 2 results queries - "Authors" and "Revenue" - in the local scope. In fact, one of the main reasons to use the Cfstoredproc tag is the ability to return multiple results sets. But now we have a problem. You see our book store is really busy. So the results that come back from this query are going to be pretty large. I don't
really want to know that I've sold 2 copies of "spitting in the wind" by Jaun A. Hockalugie. I would prefer to see the top 10 results. My manager on the other hand wants to see 25 results. How do I accomplish this in my SP?
Your first attempt (like mine) might be to use "TOP". I altered my SP as follows:
<cfquery>
CREATE PROCEDURE [dbo].[myReport]
(
@topNum int
)
WITH RECOMPILE AS
SET NOCOUNT ON
SELECT TOP @topNum count(s.saleID) AS total, a.AuthorName
FROM authors a JOIN sales s ON
a.author_id = s.author_ID
GROUP BY a.AuthorName
ORDER BY total desc
.....
</cfquery>
You can see where I was going. I thought I'd throw in a "TOP" command and variablize the number. Clever as I am I could not get this to work. T-SQL will not take a variable after TOP.
The Fix
The fix is to use the ROWCOUNT setting. The command is simply "SET ROWCOUNT N" where N is the number of rows you want to return. Setting it once at the top of a stored procedure causes any query within that procedure to stop processing as soon as it has a complete results sets with N rows that matches the WHERE and ORDER BY criteria. So my New SP code looked like this:
<cfquery>
CREATE PROCEDURE [dbo].[myReport]
(
@topNum int
)
WITH RECOMPILE AS
SET NOCOUNT ON
SET ROWCOUNT @topNum
SELECT count(s.saleID) AS total, a.AuthorName
FROM authors a JOIN sales s ON
a.author_id = s.author_ID
GROUP BY a.AuthorName
ORDER BY total desc
.....
</cfquery>
The beauty of it is that all of the subsequent queries or results sets returned from the Stored procedure are now limited in this fashion. Now I just have to include the input param in my Coldfusion code.
<Cfparam name="url.topNum" default="10"/>
<cfstoredproc datasource="myDSN" procedure="myReport" >
<cfprocparam cfsqltype="CF_SQL_INTEGER" value="#url.topNum#" dbvarname="@topNum"/>
<cfprocresult name="Authors" resultset="1"/>
<cfprocresult name="Revenue" resultset="2"/>
</cfstoredproc>
So the code above returns 10 rows for each results set.
I have one other clever use for the ROWCOUNT T-SQL setting. Sometimes when working with a schema I need to pull up a few rows from several tables. For example, when trying to create a complex JOIN query - or a view. I need to eyeball the data and column names. So instead of using a TOP keyword I simply add a rowcount command to the top of my pane in Query analyzer - setting it to 2 or 3 for example. Then I can write several queries and run them together in the lower pane - but each will be limited. It's probably not a huge time saver, but it makes cutting and pasting more reliable because I have less editing to do.