Variation on Select top n - sql-server

Is is possible to do a variation of select top n rows to select top n rows starting at a row other than 0.
My (mobile) app has limited resources and no server side caching available. The maximum rows returned is 100. I get the first 100 by select top 100. I would then like the user to be then able to request rows 101-200 and so on. The database data is static and the the re-query time negligible.
Platform SQL Server 2008

Here's an article which demonstrates such queries using the ROW_NUMBER function.

;With CTETable AS
(
SELECT ROW_NUMBER() OVER (ORDER BY Column_Name DESC) AS ROW_NUM, * FROM TABLENAME WHERE <CONDITION>
)
SELECT Column_List FROM CTETable WHERE ROWN_NUM BETWEEN <StartNum> AND <EndNum>
Use your [startNum] and [EndNum] to be any series you want maybe 123 - 147 ! This will work well !

Related

SQl Query with even distribution of samples

Is there a way to query SQL to get an even distribution of samples. For example if one of my fields is a State field... I want to query top 5000 results with (100 from each state)... Or another example, if I have a field that says whether a client is a new client or an existing client, and I want the top 500 results where 250 are new clients and 250 are existing clients.
I am trying to avoid two different queries that I have to manually combine the results.
You can do this by using ROW_NUMBER. You partition your data on one or more columns, so the row numbering starts from 1 in every partition. You then select the top x rows and ORDER BY the row number column.
e.g.
WITH cte
AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY StateName ORDER BY NEWID() ) AS RN
FROM dbo.Sales
)
SELECT TOP 5 *
FROM cte
ORDER BY RN;

SQL Server 2012 CTE Bug?

I think I found a bug in SQL Server 2012. I have the following complex query that uses CTE with row_number to accomplish paging, followed by a subquery to return total rows in a single query:
with data as ( ...complex query with row_number() ... as rowNumber... )
select *, (select count(*) from data) as totalRows
from data
where rowNumber between 1 and 10
What I'm finding in my specific query is that if the final query returns 5 rows, the totalRows comes back as 8. But there are only 5 rows. How could totalRows be bigger than the number of rows returned? I've tried query hints like disabling parallel execution plans but not only is it slower, it's still not right. Could I be doing something wrong or is this a bug? Is there another way to get the count back in one query?
Without knowing the internals of your query and ensuring you're partitioning statements are well written...
I'd suggest you are getting differences because of your where clauses. You need to be consistent and use either:
with data as ( ...complex query with row_number() ... as rowNumber... )
select *, (select count(*) from data where rowNumber between 1 and 10) as totalRows
from data
where rowNumber between 1 and 10
or
with data as ( ...complex query with row_number() ... as rowNumber... )
select *, (select count(*) from data) as totalRows
from data

SQL Server 2008 - How to show rows between 1001 to 2000

I am using SQL Server 2008. With help of TOP clause in SQL Server I have run following query to display the first 1000 rows from my table Department
Select TOP 1000 *
from Department;
Now I need to display the next 1000 data from the same table. Can anybody help me to find a solution for the this?
You can use the ROW_NUMBER function to get the number of the row, and then take the numbers from X to Y. Below query is assuming that you want the results ordered by ID:
WITH OrderedDepartments AS
(
SELECT ID, Name,
ROW_NUMBER() OVER (ORDER BY ID) AS RowNumber
FROM Department
)
SELECT ID, Name
FROM OrderedDepartments
WHERE RowNumber BETWEEN 1001 AND 2000;
you can try something like:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY DEPARTMENT_NAME) AS rownum
FROM DEPARTMENT
) AS t
WHERE t.rownum BETWEEN 1001 AND 2001
Best way is use "FETCH (Transact-SQL)", more info and sample available in following link,
FETCH (Transact-SQL)

How to replicate mysql range and limit in SQL Server using the top clause

I've been trying to replicate the limit and range feature provided in MySql in SQL Server with no luck as of yet. I have found several guides and now think my sql code is nearly correct but I'm still getting an error posted below.
System.Data.SqlClient.SqlException:
Only one expression can be specified
in the select list when the subquery
is not introduced with EXISTS
The error code says to use EXISTS but i have tried that instead of NOT IN and i still get an error.
My sql is posted below
SELECT TOP (#range) *
FROM client
WHERE clientId NOT IN
(SELECT TOP (#limit) *
FROM client
ORDER BY clientId)
ORDER BY clientId
The change you need to make to your code is
SELECT TOP (#range) *
FROM client
WHERE clientId NOT IN (SELECT TOP (#limit) clientId /*<-- NOT "*" here */
FROM client
ORDER BY clientId)
ORDER BY clientId
This can also be done by using row_number as below (which performs better depends on the different indexes available and how wide a covering index on the whole query is compared to a narrow one on just clientId.)
DECLARE #lowerlimit int
SET #lowerlimit = #range +#limit;
WITH cte As
(
SELECT TOP (#lowerlimit) * , ROW_NUMBER() OVER (ORDER BY clientId) AS RN
FROM client
ORDER BY clientId
)
SELECT * /*TODO: Your Actual column list*/
FROM cte
WHERE RN >= #limit
Another (similar, slower :) ) way
SELECT * FROM (
select rank() over (ORDER BY yourorder) as rank, *.X
from TableX X
) x2 WHERE rank between 5 and 10

What's the best method to do paging in my ASP page

What's the best method to do paging in my ASP page when displaying a list of items?
I knew that there is no equivalent to MySQL's LIMIT clause present in SQL Server, either 2000 or 2005.
How can I retrieve some particular records (Records 20 to 30) from the DB?
Do i need to fetch all the records from the database and do something in my ASP page to display the required records?
Whats the best method to do paging in my ASP page when displaying a list of items ?
I just want to add one more feature to Mr. Wheat's answer. Why not u are trying to use the Take () and Skip() feature of linq(obviously if u are using dotnet framework 3.5+)
It is indeed helpful while working with large datasets.
Have a look
Using Take and Skip method in LINQ queries
I knew that there is no MySQL LIMIT clause present in SQL server(both 2000 and 2005 should support).how can i retrieve some particular records (Record 20 -30) from DB ?
You can do this in SQLSERVER 2005+ by using ranking function Row_Number() among other alternatives. A sample example is included herewith
First I am creating a dummy table and inserting some 50 records
declare #tbl table(name varchar(50),age int)
;with num_cte as
( select 1 as rn
union all
select rn+1 from num_cte where rn<50
)
insert #tbl
select names ,rn + 20 ageval
from num_cte
cross apply( select 'name' + CAST(rn as varchar(2)) AS names) names
select * from #tbl
Now by using the Row_Number() function I am picking up records between 20 & 30
select name,age from(
select ROW_NUMBER()over (order by age) as rownum,name,age from #tbl) X
where X.rownum between 20 and 30
However, for achieving the same in SQL SERVER 2000 the below query will help
select name,age from(
select t1.name,t1.age,
(select count(*)+1 from #tbl where name<>t1.name and age<=t1.age) rownum
from #tbl t1
)X(name,age,rownum)
where rownum between 20 and 30
Please see:
Paging In ASP.NET
Data Access Tutorials
GridView Examples for ASP.NET 2.0: Paging and Sorting the GridView's Data
SQL Server 2005 Paging – The Holy Grail
Youd need to use ROW_NUMBER (SQL Server 2005+)
SELECT * FROM
(SELECT a.*, ROW_NUMBER() OVER (ORDER BY hire_date) rn
FROM hr.employees AS OF TIMESTAMP (TIMESTAMP '2009-01-29 10:30:00') a)
WHERE rn BETWEEN 10 AND 19
Related answer
Using ROW_NUMBER, you are numering and sorting the inherently unsorted group (the table). Once you have an ordered set instead of just a set, you can now the sentence "I want all the rows from 10 to 19" makes sense.
You will have to use ASP code to keep both the upper and lower elements, so you can ask for the next or previous subset of rows to show.

Resources