202

What is the simplest SQL query to find the second largest integer value in a specific column?

There are maybe duplicate values in the column.

Hash
  • 4,647
  • 5
  • 21
  • 39
Niyaz
  • 53,943
  • 55
  • 151
  • 182
  • use offset for this purpos... select extension from [dbo].[Employees] order by extension desc offset 2 rows fetch next 1 rows only – Jinto John Sep 03 '16 at 06:46
  • It depends if you want the second largest integer or the second value from the list (even if that number happens to be the same as the max number). Amazing how few answers in this thread don't consider that subtlety. – cartbeforehorse Jul 03 '23 at 14:36

46 Answers46

367
SELECT MAX( col )
  FROM table
 WHERE col < ( SELECT MAX( col )
                 FROM table )
Matt Rogish
  • 24,435
  • 11
  • 76
  • 92
  • 9
    Matt's as well as Vinoy's answer takes care of duplicates as well. Suppose the largest value is repeated then using Matt's answer will produce the correct second largest value while if you used the _top 2 desc_ and _min_ approach, you may get the largest value instead. – Pankaj Sharma Apr 01 '13 at 19:22
  • What if there are multiple second highest... Then this will not give all the Tuples – Parth Satra Oct 16 '14 at 00:09
  • 2
    thank you, used this to find second last date [here](http://stackoverflow.com/questions/8590296/sql-returning-second-newest-record/28913915#28913915) – Shaiju T Mar 07 '15 at 10:32
  • Much better than my approach using ORDER_BY and LIMIT for the inner statement – andig Oct 08 '15 at 09:58
  • Note this will not return a result if there are no records before the requested one. – andig Oct 08 '15 at 11:42
  • Works like a charm! – remykarem Jun 30 '17 at 02:44
  • This doesn't seem to work for Oracle sql. It returns all rows less than the highest value. – Shahid Sarwar Jun 06 '21 at 07:11
  • If the query has a WHERE clause (eg you want salary where department='sales'), you'll need to add it to both SELECTs, correct? – Adeptus May 16 '23 at 05:36
65
SELECT MAX(col) 
FROM table 
WHERE col NOT IN ( SELECT MAX(col) 
                   FROM table
                 );
Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
Vinoy
  • 651
  • 5
  • 2
32

In T-Sql there are two ways:

--filter out the max
select max( col )
from [table]
where col < ( 
    select max( col )
    from [table] )

--sort top two then bottom one
select top 1 col 
from (
    select top 2 col 
    from [table]
    order by col) topTwo
order by col desc 

In Microsoft SQL the first way is twice as fast as the second, even if the column in question is clustered.

This is because the sort operation is relatively slow compared to the table or index scan that the max aggregation uses.

Alternatively, in Microsoft SQL 2005 and above you can use the ROW_NUMBER() function:

select col
from (
    select ROW_NUMBER() over (order by col asc) as 'rowNum', col
    from [table] ) withRowNum 
where rowNum = 2
Keith
  • 150,284
  • 78
  • 298
  • 434
27

I see both some SQL Server specific and some MySQL specific solutions here, so you might want to clarify which database you need. Though if I had to guess I'd say SQL Server since this is trivial in MySQL.

I also see some solutions that won't work because they fail to take into account the possibility for duplicates, so be careful which ones you accept. Finally, I see a few that will work but that will make two complete scans of the table. You want to make sure the 2nd scan is only looking at 2 values.

SQL Server (pre-2012):

SELECT MIN([column]) AS [column]
FROM (
    SELECT TOP 2 [column] 
    FROM [Table] 
    GROUP BY [column] 
    ORDER BY [column] DESC
) a

MySQL:

SELECT `column` 
FROM `table` 
GROUP BY `column` 
ORDER BY `column` DESC 
LIMIT 1,1

Update:

SQL Server 2012 now supports a much cleaner (and standard) OFFSET/FETCH syntax:

SELECT [column] 
FROM [Table] 
GROUP BY [column] 
ORDER BY [column] DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY;
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • This is what I was hoping to see. The accepted answer turns ugly if you need it to work for any `n`. This one stands that test. – Robin Maben Aug 08 '12 at 06:53
  • @RobinMaben Robin, how about the scenario when the largest value is repeated? Suppose a column contains numbers 1 through 100 but 100 is repeated twice. Then this solution will produce the second largest value as 100, which will be incorrect. Right? – Pankaj Sharma Apr 01 '13 at 19:21
  • 1
    @PankajSharma no, this will still work, because of the GROUP BY clause – Joel Coehoorn Apr 01 '13 at 23:35
  • This is the standard way to do this. The accepted answer should be updated to this one. – Guilherme Melo Apr 29 '14 at 14:39
  • 1
    I get an error which says I cannot use `TOP` and `OFFSET` in the same query. – Spurious Jan 09 '15 at 13:40
  • Didn't matter, it worked anyways, the SQL 2012 solution is by far the best one out there, thank you for sharing! – Spurious Jan 09 '15 at 13:56
20

I suppose you can do something like:

SELECT * 
FROM Table 
ORDER BY NumericalColumn DESC 
LIMIT 1 OFFSET 1

or

SELECT * 
FROM Table ORDER BY NumericalColumn DESC 
LIMIT (1, 1)

depending on your database server. Hint: SQL Server doesn't do LIMIT.

Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
dguaraglia
  • 5,774
  • 1
  • 26
  • 23
  • update- SQL Server 2012 added an offset / fetch clause similar to the above http://dbadiaries.com/new-t-sql-features-in-sql-server-2012-offset-and-fetch – John Smith Jan 29 '16 at 15:50
  • Suppose you have 2 elements with same value but also the largest element. I guess you have to do `OFFSET 2` – Kangkan Sep 04 '17 at 19:17
  • Adding GROUP BY clause will cater the duplicate condition in this. – Saif Mar 20 '18 at 21:28
7

The easiest would be to get the second value from this result set in the application:

SELECT DISTINCT value 
FROM Table 
ORDER BY value DESC 
LIMIT 2

But if you must select the second value using SQL, how about:

SELECT MIN(value) 
FROM ( SELECT DISTINCT value 
       FROM Table 
       ORDER BY value DESC 
       LIMIT 2
     ) AS t
Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
Magnar
  • 28,550
  • 8
  • 60
  • 65
6

A very simple query to find the second largest value

SELECT `Column` 
FROM `Table` 
ORDER BY `Column` DESC 
LIMIT 1,1;
Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
petcy
  • 61
  • 1
  • 2
  • Only works if you want the second value from the list. In a list of `[2, 2, 1]`, this query will give you the number `2`. I think the question is asking for number `1` – cartbeforehorse Jul 03 '23 at 14:37
6

you can find the second largest value of column by using the following query

SELECT *
FROM TableName a
WHERE
  2 = (SELECT count(DISTINCT(b.ColumnName))
       FROM TableName b WHERE
       a.ColumnName <= b.ColumnName);

you can find more details on the following link

http://www.abhishekbpatel.com/2012/12/how-to-get-nth-maximum-and-minimun.html

fthiella
  • 48,073
  • 15
  • 90
  • 106
user1796141
  • 115
  • 1
  • 7
  • Archive of the dead link: https://web.archive.org/web/20130406161645/http://www.abhishekbpatel.com/2012/12/how-to-get-nth-maximum-and-minimun.html – xgMz Feb 25 '19 at 18:55
6

MSSQL

SELECT  *
  FROM [Users]
    order by UserId desc OFFSET 1 ROW 
FETCH NEXT 1 ROW ONLY;

MySQL

SELECT  *
  FROM Users
    order by UserId desc LIMIT 1 OFFSET 1

No need of sub queries ... just skip one row and select second rows after order by descending

Justine Jose
  • 130
  • 2
  • 7
4
SELECT MAX(Salary) 
FROM Employee 
WHERE Salary NOT IN ( SELECT MAX(Salary) 
                      FROM Employee 
                    )

This query will return the maximum salary, from the result - which not contains maximum salary from overall table.

Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
Naresh Kumar
  • 794
  • 8
  • 25
3

Simplest of all

select sal 
from salary 
order by sal desc 
limit 1 offset 1
Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
Sumeet
  • 1,683
  • 20
  • 27
3

Old question I know, but this gave me a better exec plan:

 SELECT TOP 1 LEAD(MAX (column)) OVER (ORDER BY column desc)
 FROM TABLE 
 GROUP BY column
dier
  • 2,791
  • 2
  • 15
  • 8
3

This is very simple code, you can try this :-

ex : Table name = test

salary 

1000
1500
1450
7500

MSSQL Code to get 2nd largest value

select salary from test order by salary desc offset 1 rows fetch next 1 rows only;

here 'offset 1 rows' means 2nd row of table and 'fetch next 1 rows only' is for show only that 1 row. if you dont use 'fetch next 1 rows only' then it shows all the rows from the second row.

melpomene
  • 84,125
  • 8
  • 85
  • 148
Nijish.
  • 31
  • 1
  • Most optimized and Resource friendly Answer. I saved quite a lot of time using it in my subquery. Thanks. – vibs2006 Feb 20 '19 at 10:41
2

select * from (select ROW_NUMBER() over (Order by Col_x desc) as Row, Col_1
    from table_1)as table_new tn inner join table_1 t1
    on tn.col_1 = t1.col_1
where row = 2

Hope this help to get the value for any row.....

Nikson Kanti Paul
  • 3,394
  • 1
  • 35
  • 51
2

Use this query.

SELECT MAX( colname ) 
FROM Tablename 
where colname < (
    SELECT MAX( colname ) 
    FROM Tablename)
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
  • 4
    This answer is identical to @Matt Rogish's answer which was posted 6 years ago and has long since been marked as correct. This answer adds nothing and should be deleted. – DMK Apr 07 '14 at 11:18
2
select max(column_name) 
from table_name
where column_name not in ( select max(column_name) 
                           from table_name
                         );

not in is a condition that exclude the highest value of column_name.

Reference : programmer interview

Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
rashedcs
  • 3,588
  • 2
  • 39
  • 40
1
SELECT 
    * 
FROM 
    table 
WHERE 
    column < (SELECT max(columnq) FROM table) 
ORDER BY 
    column DESC LIMIT 1
andrewsi
  • 10,807
  • 132
  • 35
  • 51
1

This is an another way to find the second largest value of a column.Consider the table 'Student' and column 'Age'.Then the query is,

select top 1 Age 
from Student 
where Age in ( select distinct top 2 Age  
               from Student order by Age desc 
             ) order by Age asc
Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
Pearl90
  • 115
  • 7
1

It is the most esiest way:

SELECT
      Column name
FROM
      Table name 
ORDER BY 
      Column name DESC
LIMIT 1,1
Ravind Maurya
  • 977
  • 15
  • 24
1
select age 
from student 
group by id having age< ( select max(age) 
                          from student 
                        )
order by age 
limit 1
Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
DEADLOCK
  • 19
  • 3
1

As you mentioned duplicate values . In such case you may use DISTINCT and GROUP BY to find out second highest value

Here is a table

salary

:

enter image description here

GROUP BY

SELECT  amount FROM  salary 
GROUP by amount
ORDER BY  amount DESC 
LIMIT 1 , 1

DISTINCT

SELECT DISTINCT amount
FROM  salary 
ORDER BY  amount DESC 
LIMIT 1 , 1

First portion of LIMIT = starting index

Second portion of LIMIT = how many value

Shourob Datta
  • 1,886
  • 22
  • 30
  • hey! and what if I want get second all highest value .Like from above table i want to get all 400 values? – khush Jun 10 '23 at 12:37
1
SELECT MAX(sal) 
FROM emp
WHERE sal NOT IN ( SELECT top 3 sal 
                   FROM emp order by sal desc 
                 )
            

this will return the third highest sal of emp table

Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
Swadesh
  • 61
  • 7
1

Tom, believe this will fail when there is more than one value returned in select max([COLUMN_NAME]) from [TABLE_NAME] section. i.e. where there are more than 2 values in the data set.

Slight modification to your query will work -

select max([COLUMN_NAME]) 
from [TABLE_NAME] 
where [COLUMN_NAME] IN ( select max([COLUMN_NAME]) 
                         from [TABLE_NAME] 
                       )
Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
sunith
  • 21
  • 1
1
select max(COL_NAME) 
from TABLE_NAME 
where COL_NAME in ( select COL_NAME 
                    from TABLE_NAME 
                    where COL_NAME < ( select max(COL_NAME) 
                                       from TABLE_NAME
                                      )
                   );

subquery returns all values other than the largest. select the max value from the returned list.

Ergest Basha
  • 7,870
  • 4
  • 8
  • 28
sunith
  • 21
  • 1
1
select min(sal) from emp where sal in 
    (select TOP 2 (sal) from emp order by sal desc)

Note

sal is col name
emp is table name

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Ni3
  • 11
  • 1
1
select col_name
from (
    select dense_rank() over (order by col_name desc) as 'rank', col_name
    from table_name ) withrank 
where rank = 2
Divya.N.R
  • 11
  • 2
0
select * from emp e where 3>=(select count(distinct salary)
    from emp where s.salary<=salary)

This query selects the maximum three salaries. If two emp get the same salary this does not affect the query.

sth
  • 222,467
  • 53
  • 283
  • 367
0

Using a correlated query:

Select * from x x1 where 1 = (select count(*) from x where x1.a < a)
sth
  • 222,467
  • 53
  • 283
  • 367
0

Query to find the 2nd highest number in a row-

select Top 1 (salary) from XYZ
where Salary not in (select distinct TOP 1(salary) from XYZ order by Salary desc)
ORDER BY Salary DESC

By changing the highlighted Top 1 to TOP 2, 3 or 4 u can find the 3rd, 4th and 5th highest respectively.

lc.
  • 113,939
  • 20
  • 158
  • 187
nikita
  • 1
0

We can also make use of order by and top 1 element as follows:

Select  top 1 col_name from table_name
where col_name < (Select top 1 col_name from table_name order by col_name desc)
order by col_name desc 
Abhishek Gahlout
  • 3,132
  • 2
  • 20
  • 28
0
SELECT * FROM EMP
WHERE salary=
        (SELECT MAX(salary) FROM EMP
           WHERE salary != (SELECT MAX(salary) FROM EMP)
        );
Ankur
  • 5,086
  • 19
  • 37
  • 62
ReeSen
  • 75
  • 4
0

Try:

select a.* ,b.* from 
(select * from (select ROW_NUMBER() OVER(ORDER BY fc_amount desc) SrNo1, fc_amount as amount1 From entry group by fc_amount) tbl where tbl.SrNo1 = 2) a
,
(select * from (select ROW_NUMBER() OVER(ORDER BY fc_amount asc) SrNo2, fc_amount as amount2  From entry group by fc_amount) tbl where tbl.SrNo2 =2) b
Robert
  • 5,278
  • 43
  • 65
  • 115
Gopal
  • 1
0
select * from [table] where (column)=(select max(column)from [table] where column < (select max(column)from [table]))
Tobia Zambon
  • 7,479
  • 3
  • 37
  • 69
anand
  • 1
0
select MAX(salary) as SecondMax from test where salary !=(select MAX(salary) from test)
Mitesh Vora
  • 458
  • 8
  • 21
0
select top 1 MyIntColumn from MyTable
where
 MyIntColumn <> (select top 1 MyIntColumn from MyTable order by MyIntColumn desc)
order by MyIntColumn desc
sth
  • 222,467
  • 53
  • 283
  • 367
Chris Conway
  • 16,269
  • 23
  • 96
  • 113
0

This works in MS SQL:

select max([COLUMN_NAME]) from [TABLE_NAME] where [COLUMN_NAME] < 
 ( select max([COLUMN_NAME]) from [TABLE_NAME] )
sth
  • 222,467
  • 53
  • 283
  • 367
Tom Welch
  • 172
  • 4
  • 8
0

Something like this? I haven't tested it, though:

select top 1 x
from (
  select top 2 distinct x 
  from y 
  order by x desc
) z
order by x
doekman
  • 18,750
  • 20
  • 65
  • 86
0

See How to select the nth row in a SQL database table?.

Sybase SQL Anywhere supports:

SELECT TOP 1 START AT 2 value from table ORDER BY value
Community
  • 1
  • 1
Graeme Perrow
  • 56,086
  • 21
  • 82
  • 121
0
select score 
from table 
where score = (select max(score)-1 from table)
APH
  • 4,109
  • 1
  • 25
  • 36
Hiren Joshi
  • 41
  • 1
  • 3
0

Microsoft SQL Server - Using Two TOPs for the N-th highest value (aliased sub-query).

To solve for the 2nd highest:

SELECT TOP 1 q.* 
FROM (SELECT TOP 2 column_name FROM table_name ORDER BY column_name DESC) as q
ORDER BY column_name ASC;

Uses TOP twice, but requires an aliased sub-query. Essentially, the inner query takes the greatest 2 values in descending order, then the outer query flips in ascending order so that 2nd highest is now on top. The SELECT statement returns this top.

To solve for the n-th highest value modify the sub-query TOP value. For example:

SELECT TOP 1 q.* 
FROM (SELECT TOP 5 column_name FROM table_name ORDER BY column_name DESC) as q
ORDER BY column_name;

Would return the 5th highest value.

Zorkolot
  • 1,899
  • 1
  • 11
  • 8
0
select extension from [dbo].[Employees] order by extension desc offset  2  rows fetch next  1 rows only
miken32
  • 42,008
  • 16
  • 111
  • 154
Jinto John
  • 365
  • 4
  • 22
  • Please provide more details to your answer as this post has been found in low quality post. Code only and 'try this' answers are discouraged as it doesn't provide any searchable content and why people should 'try this'. – Paritosh Sep 03 '16 at 09:46
0

Very Simple. The distinct keyword will take care of duplicates as well.

SELECT distinct SupplierID FROM [Products] order by SupplierID desc limit 1 offset 1
Mani G
  • 89
  • 11
0

The easiest way to get second last row from a SQL table is to use ORDER BYColumnNameDESC and set LIMIT 1,1.

Try this:

SELECT * from `TableName` ORDER BY `ColumnName` DESC LIMIT 1,1
Pang
  • 9,564
  • 146
  • 81
  • 122
0
 SELECT  * FROM `employee` WHERE  employee_salary = (SELECT employee_salary 
 FROM`employee` GROUP BY employee_salary ORDER BY employee_salary DESC LIMIT 
 1,1)
Amit Prajapati
  • 119
  • 1
  • 6
0

You can find nth highest value using the following query.

    select top 1 UnitPrice from (select distinct top n UnitPrice from 
[Order Details] order by UnitPrice desc) as Result order by UnitPrice asc

Here, the value of n will be 1 (for the highest number), 2 (for the second highest number), 3 (for the third highest number)...

0

At first make a dummy table without max salary then query max value from dummy table

SELECT max(salary) from (Select * FROM emp WHERE salary<> (SELECT MAX(salary) from emp)) temp
stack0114106
  • 8,534
  • 3
  • 13
  • 38