I want to select the last 5 records from a table in SQL Server without arranging the table in ascending or descending order.
-
4@Ganesh - you should phrase your question as a real question, not as a statement "I need help". – paxdiablo Nov 22 '08 at 08:04
-
It is important to understand that the sequence of records in a result of _any_ query that does not use explicit sorting via `ORDER BY` will be _non-deterministic_. If there is no sort, then there is no definition of _last_. – Chris Schaller Sep 07 '22 at 00:16
-
@Chris Schaller -- Then why does TOP (5) work? I don't understand why TOP (5) gets the top 5 without ORDER BY but there is no BOTTOM(5) OR LAST(5) that I can find. Given that TOP (5) exists, it is logical to expect something that does the opposite. Perhaps the answer is that TOP (5) starts an unlimited query that is interrupted after 5 records are returned, calling these the top or first. To get bottom one would have to get everything, then truncate the table to only give the last 5 received. As Matt Hamilton does. ??? – Blaine Kelley Nov 03 '22 at 13:32
-
@BlaineKelley having a `bottom5` is about as logical as burning a witch at the stake to prove innocence. a `BOTTOM(X)` would require processing all rows in the table and discarding them except for the last `X` records. It would be the most inefficient query in the entire SQL stack. If you don't want to order, then this indicates that your structure is not sufficient. If you have an auto-incrementing column then you can order by that column in descending order to get the top 5, whilst still preserving the data input sequence, this will be the bottom 5. – Chris Schaller Nov 03 '22 at 13:43
-
You should **NEVER** call `TOP (X)` without a corresponding `ORDER BY` clause, in many RDBMS the sequence will be indeterminate and is volatile, the database engine can re-sequence the reocrds to optimise the queries, this can mean that `TOP (5)` today can return different records to `TOP(5)` yesterday. Don't be lazy, be explicit and make sure you design your schemas to support practical sequencing. _SQL 101_ – Chris Schaller Nov 03 '22 at 13:46
22 Answers
This is just about the most bizarre query I've ever written, but I'm pretty sure it gets the "last 5" rows from a table without ordering:
select *
from issues
where issueid not in (
select top (
(select count(*) from issues) - 5
) issueid
from issues
)
Note that this makes use of SQL Server 2005's ability to pass a value into the "top" clause - it doesn't work on SQL Server 2000.

- 200,371
- 61
- 386
- 320
-
If by last, you mean in the order of the clustered key, then I'm afarid that does not work – Mitch Wheat Nov 22 '08 at 08:20
-
I tested this on a table that doesn't have a clustered index, and it returned the last five rows that I get when doing a simple "select * from issues". – Matt Hamilton Nov 22 '08 at 08:21
-
And just tried it on a table with an "identity int" primary key, and it worked there too. Got me the "last five" rows. – Matt Hamilton Nov 22 '08 at 08:22
-
-
3without order by this doesn't work. period. you might come into a situation when one query piggy backs on the results of another query and the results can be tottaly different. – Mladen Prajdic Nov 23 '08 at 17:09
Suppose you have an index on id, this will be lightning fast:
SELECT * FROM [MyTable] WHERE [id] > (SELECT MAX([id]) - 5 FROM [MyTable])

- 652
- 5
- 5
-
10This is only safe if you haven't deleted any records. ie. if your max id = 100, but you deleted record 99, you'll only end up with 4 records, not 5. – Amber Dec 18 '15 at 00:24
-
The way your question is phrased makes it sound like you think you have to physically resort the data in the table in order to get it back in the order you want. If so, this is not the case, the ORDER BY clause exists for this purpose. The physical order in which the records are stored remains unchanged when using ORDER BY. The records are sorted in memory (or in temporary disk space) before they are returned.
Note that the order that records get returned is not guaranteed without using an ORDER BY clause. So, while any of the the suggestions here may work, there is no reason to think they will continue to work, nor can you prove that they work in all cases with your current database. This is by design - I am assuming it is to give the database engine the freedom do as it will with the records in order to obtain best performance in the case where there is no explicit order specified.
Assuming you wanted the last 5 records sorted by the field Name in ascending order, you could do something like this, which should work in either SQL 2000 or 2005:
select Name
from (
select top 5 Name
from MyTable
order by Name desc
) a
order by Name asc

- 167,292
- 40
- 290
- 283
-
1This should be marked as the correct answer (and most compatible). – AshesToAshes May 11 '16 at 16:08
-
Data in tables is not always in the organised format... the idea behind the question is , what to do if we want to know the last entry in such a database – snigdha Mar 26 '20 at 12:21
-
@snigdha The answer above is trying to tell you that "last" is a concept that does not exist in SQL without ORDER BY. – D'Arcy Rittich Mar 26 '20 at 16:35
- You need to count number of rows inside table ( say we have 12 rows )
- then subtract 5 rows from them ( we are now in 7 )
select * where index_column > 7
select * from users where user_id > ( (select COUNT(*) from users) - 5)
you can order them ASC or DESC
But when using this code
select TOP 5 from users order by user_id DESC
it will not be ordered easily.

- 109
- 1
- 4
Search 5 records from last records you can use this,
SELECT *
FROM Table Name
WHERE ID <= IDENT_CURRENT('Table Name')
AND ID >= IDENT_CURRENT('Table Name') - 5

- 57,263
- 20
- 190
- 175

- 41
- 3
Without an order, this is impossible. What defines the "bottom"? The following will select 5 rows according to how they are stored in the database.
SELECT TOP 5 * FROM [TableName]

- 23,367
- 6
- 55
- 61
-
Right, also you can add an "order by colx desc" to bottom 5 depending on the indexes. ie. the top 5 *ARE* the bottom 5 if you reverse the order. – Booji Boy Nov 22 '08 at 16:27
-
This is not correct. This query will select 5 rows **but not (always)** according to how they are stored in the database. – ypercubeᵀᴹ Sep 28 '12 at 06:21
Well, the "last five rows" are actually the last five rows depending on your clustered index. Your clustered index, by definition, is the way that he rows are ordered. So you really can't get the "last five rows" without some order. You can, however, get the last five rows as it pertains to the clustered index.
SELECT TOP 5 * FROM MyTable
ORDER BY MyCLusteredIndexColumn1, MyCLusteredIndexColumnq, ..., MyCLusteredIndexColumnN DESC

- 24,293
- 14
- 43
- 56
In SQL Server 2012 you can do this :
Declare @Count1 int ;
Select @Count1 = Count(*)
FROM [Log] AS L
SELECT
*
FROM [Log] AS L
ORDER BY L.id
OFFSET @Count - 5 ROWS
FETCH NEXT 5 ROWS ONLY;

- 11,967
- 21
- 108
- 144
If you know how many rows there will be in total you can use the ROW_NUMBER() function. Here's an examble from MSDN (http://msdn.microsoft.com/en-us/library/ms186734.aspx)
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;

- 2,848
- 1
- 21
- 30
Try this, if you don't have a primary key or identical column:
select [Stu_Id],[Student_Name] ,[City] ,[Registered],
RowNum = row_number() OVER (ORDER BY (SELECT 0))
from student
ORDER BY RowNum desc

- 36,322
- 27
- 84
- 93

- 665
- 7
- 7
-
Thanks, If we have an identity_column then it was an easy job.. But I had a `View` ..So this is what I was looking for.. ! – Irf Jun 14 '18 at 07:49
-
added a [slightly modified](https://stackoverflow.com/a/50853704/1042705) version – Irf Jun 14 '18 at 09:14
Last 5 rows retrieve in mysql
This query working perfectly
SELECT * FROM (SELECT * FROM recharge ORDER BY sno DESC LIMIT 5)sub ORDER BY sno ASC
or
select sno from(select sno from recharge order by sno desc limit 5) as t where t.sno order by t.sno asc

- 4,637
- 39
- 52
- 71

- 159
- 1
- 3
When number of rows in table is less than 5 the answers of Matt Hamilton and msuvajac is Incorrect.
Because a TOP N rowcount value may not be negative.
A great example can be found Here.

- 134
- 2
- 12
i am using this code:
select * from tweets where placeID = '$placeID' and id > (
(select count(*) from tweets where placeID = '$placeID')-2)

- 12,467
- 14
- 54
- 76
select *
from table
order by empno(primary key) desc
fetch first 5 rows only

- 438,706
- 87
- 741
- 845

- 21
- 1
-
-
@JYelton - No it doesn't. Is only valid in SQL Server 2012 and ignores the "without sorting" requirement though. – Martin Smith Apr 17 '12 at 11:44
You can retrieve them from memory.
So first you get the rows in a DataSet, and then get the last 5 out of the DataSet.

- 4,853
- 8
- 38
- 57
There is a handy trick that works in some databases for ordering in database order,
SELECT * FROM TableName ORDER BY true
Apparently, this can work in conjunction with any of the other suggestions posted here to leave the results in "order they came out of the database" order, which in some databases, is the order they were last modified in.

- 56,416
- 14
- 107
- 150
In SQL Server, it does not seem possible without using ordering in the query. This is what I have used.
SELECT *
FROM
(
SELECT TOP 5 *
FROM [MyTable]
ORDER BY Id DESC /*Primary Key*/
) AS T
ORDER BY T.Id ASC; /*Primary Key*/

- 794
- 11
- 19
DECLARE @MYVAR NVARCHAR(100)
DECLARE @step int
SET @step = 0;
DECLARE MYTESTCURSOR CURSOR
DYNAMIC
FOR
SELECT col FROM [dbo].[table]
OPEN MYTESTCURSOR
FETCH LAST FROM MYTESTCURSOR INTO @MYVAR
print @MYVAR;
WHILE @step < 10
BEGIN
FETCH PRIOR FROM MYTESTCURSOR INTO @MYVAR
print @MYVAR;
SET @step = @step + 1;
END
CLOSE MYTESTCURSOR
DEALLOCATE MYTESTCURSOR

- 3,445
- 1
- 20
- 16
Thanks to @Apps Tawale , Based on his answer, here's a bit of another (my) version,
To select last 5 records without an identity column,
select top 5 *,
RowNum = row_number() OVER (ORDER BY (SELECT 0))
from [dbo].[ViewEmployeeMaster]
ORDER BY RowNum desc
Nevertheless, it has an order by, but on RowNum :)
Note(1): The above query will reverse the order of what we get when we run the main select query.
So to maintain the order, we can slightly go like:
select *, RowNum2 = row_number() OVER (ORDER BY (SELECT 0))
from (
select top 5 *, RowNum = row_number() OVER (ORDER BY (SELECT 0))
from [dbo].[ViewEmployeeMaster]
ORDER BY RowNum desc
) as t1
order by RowNum2 desc
Note(2): Without an identity column, the query takes a bit of time in case of large data

- 4,285
- 3
- 36
- 49
Get the count of that table
select count(*) from TABLE
select top count * from TABLE where 'primary key row' NOT IN (select top (count-5) 'primary key row' from TABLE)

- 18,415
- 4
- 40
- 50

- 1
If you do not want to arrange the table in ascending or descending order. Use this.
select * from table limit 5 offset (select count(*) from table) - 5;

- 584
- 9
- 17