SQL query query about selecting particular number of rows - sql

For example -
SELECT * FROM user_names returns about 100 rows.
How would you query to get only row no.30 to row no.40?

Well with MySQL you would do it as follows:
SELECT * FROM user_names LIMIT 30,10

you can use row_number
with CTE_Table
as (SELECT id, ROW_NUMBER() OVER(ORDER BY id DESC) AS Row_Number
FROM dbo.a)
select * from CTE_Table
WHERE Row_Number BETWEEN 30 AND 40

Assuming SQL Server
SELECT * FROM
(SELECT ROW_NUMBER() OVER (ORDER BY user_names.id) as RowNumber, *
from user_names) un
where un.RowNumber between 30 and 40
replace the ORDER BY clause with whatever you want to order by.

Related

Pagination of large dataset

I have a query that returns a large (10000+ rows) dataset. I want to order by date desc, and display the first 40 results. Is there a way to run a query like this that only retrieves those 40 results without retrieving all 10000 first?
I have something like this:
select rownum, date, * from table
order by date desc
This selects all the data and orders it by date, but the rownum is not in order so it is useless for selecting only the first 40.
ROW_NUMBER() over (ORDER BY date desc) AS rowNumber
^ Will display a rownumber in order, but I can't use it in a where clause because it is a window function. I could run this:
select * from (select ROW_NUMBER() over (ORDER BY date desc) AS rowNumber,
rownum, * from table
order by date desc) where rowNumber between pageStart and pageEnd
but this is selecting all 10000 rows. How can I do this efficiently?
SELECT *
FROM (SELECT *
FROM table
ORDER BY date DESC)
WHERE rownum <= 40
will return the first 40 rows ordered by date. If there is an index on date that can be used to find these rows, and assuming statistics are up to date, Oracle should choose to use that index to identify the 40 rows that you want and then do 40 single-row lookups against the table to retrieve the rest of the data. You could throw a /*+ first_rows(40) */ hint into the inner query if you want though that shouldn't have any effect.
For a more general discussion on pagination queries and Top N queries, here's a nice discussion from Tom Kyte and a much longer AskTom discussion.
Oracle 12c has introduced a row limiting clause:
SELECT *
FROM table
ORDER BY "date" DESC
FETCH FIRST 40 ROWS ONLY;
In earlier versions you can do:
SELECT *
FROM ( SELECT *
FROM table
ORDER BY "date" DESC )
WHERE ROWNUM <= 40;
or
SELECT *
FROM ( SELECT *,
ROW_NUMBER() OVER ( ORDER BY "date" DESC ) AS RN
FROM table )
WHERE RN <= 40;
or
SELECT *
FROM TEST
WHERE ROWID IN ( SELECT ROWID
FROM ( SELECT "Date" FROM TEST ORDER BY "Date" DESC )
WHERE ROWNUM <= 40 );
Whatever you do, the database will need to look through all the values in the date column to find the 40 first items.
You don't need a window function. See
http://www.techonthenet.com/oracle/questions/top_records.php
for an answer to your problem.

Select Top 100 Groups

I have thousands of groups in a table, something like :
1..
1..
2..
2..
2..
2..
3..
3..
.
.
.
10000..
10000..
How can i make a select that give me the Top 3 groups each time.
I Want something like select Top 3 from rows , but it have to return the first three groups not the first three rows.
You can try this :
;with cte as (
select distinct groupId from mytable order by groupid
)
select * from mytable where TheGroupId in (select top 3 groupdid from cte)
You can use DENSE_RANK to assign a number to each group. All members of the same group will have the same number. Then in an outer query, select top 3 groups:
SELECT *
FROM (SELECT *, DENSE_RANK() OVER (ORDER BY id) AS rnk
FROM mytable ) t
WHERE t.rnk <= 3
The above query assumes that id is the column used to group records together.
SQL Fiddle Demo
Use Ranking function Row_Number() :
SELECT *
FROM (SELECT *,
Row_number()
OVER(
partition BY GroupId
ORDER BY GroupId) AS [rn]
FROM YourTable) t
WHERE rn <= 3
Check this MSDN doc for details of all ranking functions.
There is a sql TOP statement that does this
SELECT TOP number|percent column_name(s) FROM table_name;
a description of what it does and how it is used in alternative sql statements for example for mysql and ms access can be found here: http://www.w3schools.com/sql/sql_top.asp
My bad i misread your question, this will return the top rows not groups, could you explain what you are trying to do in more detail?
SELECT *
FROM
(SELECT *
,ROW_NUMBER() OVER (PARTITION BY [Group] ORDER BY [Group] ASC)rn
FROM TableName
)A
WHERE rn <= 3

How to select a row based on its row number?

I'm working on a small project in which I'll need to select a record from a temporary table based on the actual row number of the record.
How can I select a record based on its row number?
A couple of the other answers touched on the problem, but this might explain. There really isn't an order implied in SQL (set theory). So to refer to the "fifth row" requires you to introduce the concept
Select *
From
(
Select
Row_Number() Over (Order By SomeField) As RowNum
, *
From TheTable
) t2
Where RowNum = 5
In the subquery, a row number is "created" by defining the order you expect. Now the outer query is able to pull the fifth entry out of that ordered set.
Technically SQL Rows do not have "RowNumbers" in their tables. Some implementations (Oracle, I think) provide one of their own, but that's not standard and SQL Server/T-SQL does not. You can add one to the table (sort of) with an IDENTITY column.
Or you can add one (for real) in a query with the ROW_NUMBER() function, but unless you specify your own unique ORDER for the rows, the ROW_NUMBERS will be assigned non-deterministically.
What you're looking for is the row_number() function, as Kaf mentioned in the comments.
Here is an example:
WITH MyCte AS
(
SELECT employee_id,
RowNum = row_number() OVER ( order by employee_id )
FROM V_EMPLOYEE
ORDER BY Employee_ID
)
SELECT employee_id
FROM MyCte
WHERE RowNum > 0
There are 3 ways of doing this.
Suppose u have an employee table with the columns as emp_id, emp_name, salary. You need the top 10 employees who has highest salary.
Using row_number() analytic function
Select * from
( select emp_id,emp_name,row_number() over (order by salary desc) rank
from employee)
where rank<=10
Using rank() analytic function
Select * from
( select emp_id,emp_name,rank() over (order by salary desc) rank
from employee)
where rank<=10
Using rownum
select * from
(select * from employee order by salary desc)
where rownum<=10;
This will give you the rows of the table without being re-ordered by some set of values:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT '1')) AS RowID, * FROM #table
If using SQL Server 2012 you can now use offset/fetch:
declare #rowIndexToFetch int
set #rowIndexToFetch = 0
select
*
from
dbo.EntityA ea
order by
ea.Id
offset #rowIndexToFetch rows
fetch next 1 rows only

Apply aggregate function on subset of rows

I have a table that I want to calculate the average of one column but only for the last 10 rows.
SELECT AVG(columnName) as avg FROM tableName
I cannot apply top directly since this query only returns one row. I need a way to get the latest 10 rows and do the average on them.
Try this:
SELECT AVG(columnName) FROM
(SELECT TOP 10 columnName FROM tableName ORDER BY ColumnWhichHoldsOrder DESC) A
select avg(columnName)
from (
select columnName,
row_number() over (order by some column desc) as rn
from tableName
) t
where rn <= 10;

Get rows from the table using row no in sql server

I want to get rows from 100-150 from my table in sql server 2008, how i can do that? Is there any way to do so? as much i search Limit keyword is available in mysql but for sql server use common table technique but i don't want to do like that is there any other way available as it is available in Mysql?
select * from
(select row_number() over (order by #column) as row,* from Table) as t
where row between 100 and 150
#column to be replaced by a colomn from your table witch well be used to order the result
use sql limit
http://php.about.com/od/mysqlcommands/g/Limit_sql.htm
In SQL 2005 and above there is a ROW_NUMBER() function. If you need something that works for both MySQL and SQL Server though then I don't know if this is available in MySQL as I've never used it.
http://msdn.microsoft.com/en-us/library/ms186734.aspx
The example given in the linked page that seems most relevant is the following, where the results of a query are ordered by date, and then rows 50 to 60 from that result set are returned.
USE AdventureWorks2012;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
FROM Sales.SalesOrderHeader
)
SELECT SalesOrderID, OrderDate, RowNumber
FROM OrderedOrders
WHERE RowNumber BETWEEN 50 AND 60;
Actuall, the least expensive way to do this is using top, and then row_number()
select *
from (select *, row_number() over (order by (select NULL)) as rownum
from (select top 150 t.*
from t
) t
) t
where rownum >= 100
However, I do give you one caution. There is no such thing as rows 100-150 in a relational table, because these are inherently unordered. You need to specify the ordering. For this, you need order by:
select *
from (select *, row_number() over (order by <field>) as rownum
from (select top 150 t.*
from t
order by <field>
) t
) t
where rownum >= 100