In SQL Server, TOP may be used to return the first n number of rows in a query. For example, SELECT TOP 100 * FROM users ORDER BY id might be used to return the first 100 people that registered for a site. (This is not necessarily the best way, I am just using it as an example).
My question is - What is the equivalent to TOP in other databases, such as Oracle, MySQL, PostgreSQL, etc? If there is not an equivalent keyword, what workarounds can you recommend to achieve the same result?
To select first 100 rows:
MySQL and PostgreSQL:
SELECT *
FROM Table
ORDER BY
column
LIMIT 100
Oracle:
SELECT *
FROM (
SELECT t.*
FROM table
ORDER BY
column
)
WHERE rownum <= 100
Note that you need a subquery here. If you don't add a subquery, ROWNUM will select first 10 rows in random order and then sort them by column.
To select rows between 100 and 300:
MySQL:
SELECT *
FROM TABLE
ORDER BY
column
LIMIT 100, 200
PostgreSQL:
SELECT *
FROM Table
ORDER BY
column
OFFSET 100 LIMIT 200
Oracle:
SELECT *
FROM (
SELECT t.*, ROW_NUMBER() OVER (ORER BY column) AS rn
FROM table
)
WHERE rn >= 100
AND rownum <= 200
Note that an attempt to simplify it with ROWNUM BETWEEN 100 AND 200 (as opposed to rn BETWEEN 100 AND 200 in the outer query) will return nothing in Oracle!
RN BETWEEN 100 AND 200 will work in Oracle too but is less efficient.
See the article in my blog for performance details:
Oracle: ROW_NUMBER vs ROWNUM
For Postgres and MySQL it's the LIMIT keyword.
SELECT *
FROM users
ORDER BY id
LIMIT 100;
This is standard SQL (Oracle and SQL Server implement it). This is an example of returning up to 100 rows:
SELECT ID_CONTROL FROM (SELECT ROW_NUMBER() OVER (ORDER BY ID_CONTROL)
ROWNUMBER, ID_CONTROL FROM IWS_CONTROL WHERE
CURRENT_STATE = 15 AND CURRENT_STATUS=0) A WHERE ROWNUMBER <= 100)
In SQL Anywhere, it's the same as SQL Server:
SELECT TOP 100 * FROM users ORDER BY id
You can even start in the middle of the result set if you want:
SELECT TOP 100 START AT 50 * FROM users ORDER BY id
gets the 50th through 150th rows of the result set.
LIMIT 100
as in
SELECT * FROM foo ORDER BY bar LIMIT 100
You can use RANK() and DENSE_RANK() in Oracle. Here is a link to AskTom website explaining how to to pagination and top-n queries with DENSE_RANK in Oracle.
Oracle:
select * from (select * from foo ORDER BY bar) where rownum < 100
With a nice explanation on how to make it work in AskTom.
In Ingres the same query would by:
select First 100 * from foo ORDER BY bar
Ingres question was already answered in StackOverflow before.
In DB2 you would make your query look like this:
SELECT * FROM tblData FETCH FIRST 10 ROWS ONLY;
In Oracle you want to use a TOP-N query.
For example:
select *
from (SELECT *
FROM foo
where foo_id=[number]
order by foo_id desc)
where rownum <= 3
This will get you the top three results (because I order by desc in the sub query)
Related
Suppose I have 500 records in tbl_students. I would like to select records starting from 50 and 250. I know I can use the following way in MySql.
SELECT *
FROM tbl_students
LIMIT 50,100;
I would like to know how to do this in SQL Server. After browsing I have found solution like this.
select top 100 *
from tablename
WHERE column_name BETWEEN 50 AND 250
The issue I am facing is I do not know the values of any column in the table, so I can't write the query like the above. In MySql we can just put the limit for the range without knowing the values inside the column.
Thanks in advance
If you're using SQL Server 2005/08, then you could use a CTE...
;WITH cteRange as
(
select *, rownumber=ROW_NUMBER() OVER (Order by field)
from tablename
)
SELECT * FROM cteRange WHERE rownumber BETWEEN 50 AND 250
if you have SQL Server 2012, then...
SELECT
*
FROM tablename
ORDER BY field
OFFSET 50 ROWS
FETCH NEXT 200 ROWS ONLY
It would be useful to know RDBMS and also what columns you want to extract and Order by, instead of using SELECT *...
It's not clear by what column(s) you want to sort. A table has no implicit order, so you cannot say "give me records between x and y" if you don't specify how you want to order the records.
However, assuming that column_name is the column that you want to use and you're using SQL Server 2005 or newer, you can use a CTE with ROW_NUMBER window function:
WITH CTE AS
(
SELECT t.*, R = ROW_NUMBER() OVER (ORDER BY column_name)
FROM dbo.TableName t
)
SELECT * FROM CTE WHERE RN BETWEEN 50 AND 250
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY column_name ) as tbl_row FROM tbl_students
) tbl WHERE tbl_row >= 50 and tbl_row <= 250
I think this is one of way available for doing this in SQL Server above version 2005.
How can i find the fifth record in a table using sql query?
If you are feeling argumentative, consider using "SELECT * FROM table LIMIT 1" and arguing that since SQL does not promise to return results in any particular order, the row returned is spiritually equivalent to the fifth, then show your tattoo: "The nth element of an unordered set is meaningless!"
SELECT TOP 1 * FROM (SELECT TOP 5 * FROM Table T ORDER BY Column ASC) ORDER BY Column Desc
If you are using SqlServer you could use the TOP keyword to achieve this.
select top 1 * from(
select top 5 * from myTable order by orderingColumn) as A
order by orderingColumn desc
If you are using Oracle this should work (however i am not able to test this now)
select *
from (
select *, row_number() over (order by orderingColumn) r
from items
)
where r = 5;
SELECT * FROM table LIMIT 1 OFFSET 4;
Fifth record only in MySQL
SELECT * FROM anytable LIMIT ORDER BY id LIMIT 4,1
For SQL Server (recent-ish incarnations, anyway) something like this should work:
SELECT
*
FROM
(
SELECT
*,
ROW_NUMBER() OVER (ORDER BY the_table.the_column) 'row_num'
FROM
the_table
) numbered_rows
WHERE
row_num = 5
However, I'd actually put my vote with Thomas L Holaday's answer :)
I have an SQL Query that i'm running but I only want to select a specific row. For example lets say my query was:
Select * from Comments
Lets say this returns 10 rows, I only want to select the 8th record returned by this query. I know I can do:
Select Top 5 * from Comments
To get the top 5 records of that query but I only want to select a certain record, is there anything I can put into this query to do that (similar to top).
Thanks
jack
This is a classic interview question.
In Ms SQL 2005+ you can use the ROW_NUMBER() keyword and have the Predicate ROW_NUMBER = n
USE AdventureWorks;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
FROM Sales.SalesOrderHeader
)
SELECT *
FROM OrderedOrders
WHERE RowNumber = 5;
In SQL2000 you could do something like
SELECT Top 1 *FROM
[tblApplications]
where [ApplicationID] In
(
SELECT TOP 5 [ApplicationID]
FROM [dbo].[tblApplications]
order by applicationId Desc
)
How about
SELECT TOP 1 * FROM
(SELECT TOP 8 * FROM Comments ORDER BY foo ASC)
ORDER BY foo DESC
First, you should say which RDBMS you're using.
Second, you should give careful thought to what it is you're trying to accomplish. Relational Databases are set-based. In general, the order of elements in a set does not matter. You'll want to ask why it matters in this case, then see if there's a better way to embed the concept of order into the query itself.
For instance, in SQL Server 2005 (and other RDBMS), you can use the ROW_NUMBER function to assign a sequential number to each row returned, based on the criteria you specify. You could then select rows based on the row number. Example from Books Online:
USE AdventureWorks;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
FROM Sales.SalesOrderHeader
)
SELECT *
FROM OrderedOrders
WHERE RowNumber BETWEEN 50 AND 60;
SELECT * FROM comments WHERE ...conditions... LIMIT 1 OFFSET 8
OFFSET is a good thing for MySQL
For SQL Server 2005:
select rank() OVER (ORDER BY c.subject, c.date) as rank, c.subject, c.date
from comments c
where rank = 8
Well, in T-SQL (the dialect for SQL Server) you can do the following:
SELECT TOP 1 *
FROM (SELECT TOP 8 *
FROM Table
ORDER
BY SortField)
ORDER
BY SortField DESC
This way you get the 8th record.
I have read the question & your comments on you would want next 3 blog comments etc.
How is your tables structured?
Assume that you have blog post Id & comment Id is generated in ascending order for each blog post, you could do a SELECT based on the current Id.
e.g. if the blogpostId = 101, you get the top 3 comments order by posted Id. Now lets say, you want to get the next 3 comments - you could do a SELECT WHERE commentId between the last comment id shown TO the comment id - 3
But all that depends on how your tables are defined.
In SQL 2000 where you do not have ROW_NUMBER() function you could use a work-around like this:
SELECT CommentsTableFieldList, IDENTITY(INT, 1,1) as seqNo
INTO #SeqComments
FROM Comments
SELECT * FROM #SeqComments
WHERE seqNo = 8
select top 1 *
from TableName
where ColumnName1 in
(
select top nth ColumnName1
from TableName
order by ColumnName1 desc
)
order by ColumnName1 desc
From the SELECT reference, use the LIMIT keyword:
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
Note: this is for MySQL, other SQL engines may have a different keyword.
Select from tablename limit nthrow,1;
try This
Let us assume , We want select 5th row of WC_Video Table
And
Select * from (Select Row_Number() over (Order by Uploadedon) as 'rownumber',* from Wc_Video )as Temp where rownumber=5
I'm trying to do something like :
SELECT * FROM table LIMIT 10,20
or
SELECT * FROM table LIMIT 10 OFFSET 10
but using SQL Server
The only solution I found looks like overkill:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases
) a WHERE row > 5 and row <= 10
I also found:
SELECT TOP 10 * FROM stuff;
... but it's not what I want to do since I can't specify the starting limit.
Is there another way for me to do that ?
Also, just curious, is there a reason why doesn't SQL Server support the LIMIT function or something similar? I don't want to be mean, but that really sounds like something a DBMS needs ... If it does, then I'm sorry for being so ignorant! I've been working with MySQL and SQL+ for the past 5 years so...
For SQL Server 2012 + you can use.
SELECT *
FROM sys.databases
ORDER BY name
OFFSET 5 ROWS
FETCH NEXT 5 ROWS ONLY
The LIMIT clause is not part of standard SQL. It's supported as a vendor extension to SQL by MySQL, PostgreSQL, and SQLite.
Other brands of database may have similar features (e.g. TOP in Microsoft SQL Server), but these don't always work identically.
It's hard to use TOP in Microsoft SQL Server to mimic the LIMIT clause. There are cases where it just doesn't work.
The solution you showed, using ROW_NUMBER() is available in Microsoft SQL Server 2005 and later. This is the best solution (for now) that works solely as part of the query.
Another solution is to use TOP to fetch the first count + offset rows, and then use the API to seek past the first offset rows.
See also:
"Emulate MySQL LIMIT clause in Microsoft SQL Server 2000"
"Paging of Large Resultsets in ASP.NET"
as you found, this is the preferred sql server method:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases
) a WHERE a.row > 5 and a.row <= 10
How about this?
SET ROWCOUNT 10
SELECT TOP 20 *
FROM sys.databases
ORDER BY database_id DESC
It gives you the last 10 rows of the first 20 rows. One drawback is that the order is reversed, but, at least it's easy to remember.
If you are using SQL Server 2012+ vote for Martin Smith's answer and use the OFFSET and FETCH NEXT extensions to ORDER BY,
If you are unfortunate enough to be stuck with an earlier version, you could do something like this,
WITH Rows AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY [dbo].[SomeColumn]) [Row]
, *
FROM
[dbo].[SomeTable]
)
SELECT TOP 10
*
FROM
Rows
WHERE Row > 10
I believe is functionaly equivalent to
SELECT * FROM SomeTable LIMIT 10 OFFSET 10 ORDER BY SomeColumn
and the best performing way I know of doing it in TSQL, before MS SQL 2012.
If there are very many rows you may get better performance using a temp table instead of a CTE.
Unfortunately, the ROW_NUMBER() is the best you can do. It's actually more correct, because the results of a limit or top clause don't really have meaning without respect to some specific order. But it's still a pain to do.
Update: Sql Server 2012 adds a limit -like feature via OFFSET and FETCH keywords. This is the ansi-standard approach, as opposed to LIMIT, which is a non-standard MySql extension.
SELECT TOP 10 *
FROM TABLE
WHERE IDCOLUMN NOT IN (SELECT TOP 10 IDCOLUMN FROM TABLE)
Should give records 11-20.
Probably not too efficient if incrementing to get further pages, and not sure how it might be affected by ordering.
Might have to specify this in both WHERE statements.
A good way is to create a procedure:
create proc pagination (#startfrom int ,#endto int) as
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY name desc) as row FROM sys.databases
) a WHERE a.row > #startfrom and a.row <= #endto
just like limit 0,2
///////////////
execute pagination 0,4
Just for the record solution that works across most database engines though might not be the most efficient:
Select Top (ReturnCount) *
From (
Select Top (SkipCount + ReturnCount) *
From SourceTable
Order By ReverseSortCondition
) ReverseSorted
Order By SortCondition
Pelase note: the last page would still contain ReturnCount rows no matter what SkipCount is. But that might be a good thing in many cases.
The equivalent of LIMIT is SET ROWCOUNT, but if you want generic pagination it's better to write a query like this:
;WITH Results_CTE AS
(
SELECT
Col1, Col2, ...,
ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum
FROM Table
WHERE <whatever>
)
SELECT *
FROM Results_CTE
WHERE RowNum >= #Offset
AND RowNum < #Offset + #Limit
select * from (select id,name,ROW_NUMBER() OVER (ORDER BY id asc) as row
from tableName1) tbl1
where tbl1.row>=10 and tbl1.row<=15
Will print rows from 10 to 15.
So far this format is what is working for me (not the best performance though):
SELECT TOP {desired amount of rows} *
FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY {order columns} asc)__row__ FROM {table})tmp
WHERE __row__ > {offset row count}
A note on the side, paginating over dynamic data can lead to strange/unexpected results.
From the MS SQL Server online documentation (http://technet.microsoft.com/en-us/library/ms186734.aspx
), here is their example that I have tested and works, for retrieving a specific set of rows. ROW_NUMBER requires an OVER, but you can order by whatever you like:
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;
Use all SQL server:
;with tbl as (SELECT ROW_NUMBER() over(order by(select 1)) as RowIndex,* from table)
select top 10 * from tbl where RowIndex>=10
SELECT * FROM users WHERE Id Between 15 and 25
it will print from 15 to 25 as like limit in MYSQl
This question already has answers here:
Implement paging (skip / take) functionality with this query
(6 answers)
Closed 1 year ago.
I have this query with MySQL:
select * from table1 LIMIT 10,20
How can I do this with SQL Server?
Starting SQL SERVER 2005, you can do this...
USE AdventureWorks;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
FROM Sales.SalesOrderHeader
)
SELECT *
FROM OrderedOrders
WHERE RowNumber BETWEEN 10 AND 20;
or something like this for 2000 and below versions...
SELECT TOP 10 * FROM (SELECT TOP 20 FROM Table ORDER BY Id) ORDER BY Id DESC
Starting with SQL SERVER 2012, you can use the OFFSET FETCH Clause:
USE AdventureWorks;
GO
SELECT SalesOrderID, OrderDate
FROM Sales.SalesOrderHeader
ORDER BY SalesOrderID
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
GO
http://msdn.microsoft.com/en-us/library/ms188385(v=sql.110).aspx
This may not work correctly when the order by is not unique.
If the query is modified to ORDER BY OrderDate, the result set returned is not as expected.
This is how I limit the results in MS SQL Server 2012:
SELECT *
FROM table1
ORDER BY columnName
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
NOTE: OFFSET can only be used with or in tandem to ORDER BY.
To explain the code line OFFSET xx ROWS FETCH NEXT yy ROW ONLY
The xx is the record/row number you want to start pulling from in the table, i.e: If there are 40 records in table 1, the code above will start pulling from row 10.
The yy is the number of records/rows you want to pull from the table.
To build on the previous example: If table 1 has 40 records and you began pulling from row 10 and grab the NEXT set of 10 (yy).
That would mean, the code above will pull the records from table 1 starting at row 10 and ending at 20. Thus pulling rows 10 - 20.
Check out the link for more info on OFFSET
This is almost a duplicate of a question I asked in October:
Emulate MySQL LIMIT clause in Microsoft SQL Server 2000
If you're using Microsoft SQL Server 2000, there is no good solution. Most people have to resort to capturing the result of the query in a temporary table with a IDENTITY primary key. Then query against the primary key column using a BETWEEN condition.
If you're using Microsoft SQL Server 2005 or later, you have a ROW_NUMBER() function, so you can get the same result but avoid the temporary table.
SELECT t1.*
FROM (
SELECT ROW_NUMBER OVER(ORDER BY id) AS row, t1.*
FROM ( ...original SQL query... ) t1
) t2
WHERE t2.row BETWEEN #offset+1 AND #offset+#count;
You can also write this as a common table expression as shown in #Leon Tayson's answer.
SELECT *
FROM (
SELECT TOP 20
t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn
FROM table1 t
ORDER BY
field1
) t
WHERE rn > 10
Syntactically MySQL LIMIT query is something like this:
SELECT * FROM table LIMIT OFFSET, ROW_COUNT
This can be translated into Microsoft SQL Server like
SELECT * FROM
(
SELECT TOP #{OFFSET+ROW_COUNT} *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum
FROM table
) a
WHERE rnum > OFFSET
Now your query select * from table1 LIMIT 10,20 will be like this:
SELECT * FROM
(
SELECT TOP 30 *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum
FROM table1
) a
WHERE rnum > 10
SELECT TOP 10 * FROM table;
Is the same as
SELECT * FROM table LIMIT 0,10;
Here's an article about implementing Limit in MsSQL Its a nice read, specially the comments.
This is one of the reasons I try to avoid using MS Server... but anyway. Sometimes you just don't have an option (yei! and I have to use an outdated version!!).
My suggestion is to create a virtual table:
From:
SELECT * FROM table
To:
CREATE VIEW v_table AS
SELECT ROW_NUMBER() OVER (ORDER BY table_key) AS row,* FROM table
Then just query:
SELECT * FROM v_table WHERE row BETWEEN 10 AND 20
If fields are added, or removed, "row" is updated automatically.
The main problem with this option is that ORDER BY is fixed. So if you want a different order, you would have to create another view.
UPDATE
There is another problem with this approach: if you try to filter your data, it won't work as expected. For example, if you do:
SELECT * FROM v_table WHERE field = 'test' AND row BETWEEN 10 AND 20
WHERE becomes limited to those data which are in the rows between 10 and 20 (instead of searching the whole dataset and limiting the output).
In SQL there's no LIMIT keyword exists. If you only need a limited number of rows you should use a TOP keyword which is similar to a LIMIT.
Must try. In below query, you can see group by, order by, Skip rows, and limit rows.
select emp_no , sum(salary_amount) from emp_salary
Group by emp_no
ORDER BY emp_no
OFFSET 5 ROWS -- Skip first 5
FETCH NEXT 10 ROWS ONLY; -- limit to retrieve next 10 row after skiping rows
Easy way
MYSQL:
SELECT 'filds' FROM 'table' WHERE 'where' LIMIT 'offset','per_page'
MSSQL:
SELECT 'filds' FROM 'table' WHERE 'where' ORDER BY 'any' OFFSET 'offset'
ROWS FETCH NEXT 'per_page' ROWS ONLY
ORDER BY is mandatory
This is a multi step approach that will work in SQL2000.
-- Create a temp table to hold the data
CREATE TABLE #foo(rowID int identity(1, 1), myOtherColumns)
INSERT INTO #foo (myColumns) SELECT myData order By MyCriteria
Select * FROM #foo where rowID > 10
SELECT
*
FROM
(
SELECT
top 20 -- ($a) number of records to show
*
FROM
(
SELECT
top 29 -- ($b) last record position
*
FROM
table -- replace this for table name (i.e. "Customer")
ORDER BY
2 ASC
) AS tbl1
ORDER BY
2 DESC
) AS tbl2
ORDER BY
2 ASC;
-- Examples:
-- Show 5 records from position 5:
-- $a = 5;
-- $b = (5 + 5) - 1
-- $b = 9;
-- Show 10 records from position 4:
-- $a = 10;
-- $b = (10 + 4) - 1
-- $b = 13;
-- To calculate $b:
-- $b = ($a + position) - 1
-- For the present exercise we need to:
-- Show 20 records from position 10:
-- $a = 20;
-- $b = (20 + 10) - 1
-- $b = 29;
If your ID is unique identifier type or your id in table is not sorted you must do like this below.
select * from
(select ROW_NUMBER() OVER (ORDER BY (select 0)) AS RowNumber,* from table1) a
where a.RowNumber between 2 and 5
The code will be
select * from limit 2,5
better use this in MSSQLExpress 2017.
SELECT * FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) as [Count], * FROM table1
) as a
WHERE [Count] BETWEEN 10 and 20;
--Giving a Column [Count] and assigning every row a unique counting without ordering something then re select again where you can provide your limits.. :)
One of the possible way to get result as below , hope this will help.
declare #start int
declare #end int
SET #start = '5000'; -- 0 , 5000 ,
SET #end = '10000'; -- 5001, 10001
SELECT * FROM (
SELECT TABLE_NAME,TABLE_TYPE, ROW_NUMBER() OVER (ORDER BY TABLE_NAME) as row FROM information_schema.tables
) a WHERE a.row > #start and a.row <= #end
If i remember correctly (it's been a while since i dabbed with SQL Server) you may be able to use something like this: (2005 and up)
SELECT
*
,ROW_NUMBER() OVER(ORDER BY SomeFields) AS [RowNum]
FROM SomeTable
WHERE RowNum BETWEEN 10 AND 20