What is the simplest SQL Query to find the second largest value? - sql

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.

SELECT MAX( col )
FROM table
WHERE col < ( SELECT MAX( col )
FROM table )

SELECT MAX(col)
FROM table
WHERE col NOT IN ( SELECT MAX(col)
FROM table
);

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

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;

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.

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

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

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

A very simple query to find the second largest value
SELECT `Column`
FROM `Table`
ORDER BY `Column` DESC
LIMIT 1,1;

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.

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

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.

Simplest of all
select sal
from salary
order by sal desc
limit 1 offset 1

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.....

Use this query.
SELECT MAX( colname )
FROM Tablename
where colname < (
SELECT MAX( colname )
FROM Tablename)

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

select col_name
from (
select dense_rank() over (order by col_name desc) as 'rank', col_name
from table_name ) withrank
where rank = 2

SELECT
*
FROM
table
WHERE
column < (SELECT max(columnq) FROM table)
ORDER BY
column DESC LIMIT 1

It is the most esiest way:
SELECT
Column name
FROM
Table name
ORDER BY
Column name DESC
LIMIT 1,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
:
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

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]
)

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.

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

select age
from student
group by id having age< ( select max(age)
from student
)
order by age
limit 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

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

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

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

Using a correlated query:
Select * from x x1 where 1 = (select count(*) from x where x1.a < a)

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.

Related

oracle sql wih rownum <=

why below query is not giving results if I remove the < sign from query.Because even without < it must match with results?
Query used to get second max id value:
select min(id)
from(
select distinct id
from student
order by id desc
)
where rownum <=2
student id
1
2
3
4
Rownum has a special meaning in Oracle. It is increased with every row, but the optimizer knows that is increasing continuously and all consecutive rows must met the rownum condition. So if you specify rownum = 2 it will never occur since the first row is already rejected.
You can see this very nice if you do an explain plan on your query. It will show something like:
Plan for rownum <=:
COUNT STOPKEY
Plan for rownum =:
FILTER
A ROWNUM value is not assigned permanently to a row (this is a common misconception). A row in a table does not have a number; you cannot ask for row 2 or 3 from a table
click Here for more Info.
This is from the link provided:
Also confusing to many people is when a ROWNUM value is actually assigned. A ROWNUM value is assigned to a row after it passes the predicate phase of the query but before the query does any sorting or aggregation. Also, a ROWNUM value is incremented only after it is assigned, which is why the following query will never return a row:
select *
from t
where ROWNUM > 1;
Because ROWNUM > 1 is not true for the first row, ROWNUM does not advance to 2. Hence, no ROWNUM value ever gets to be greater than 1. Consider a query with this structure:
select ..., ROWNUM
from t
where <where clause>
group by <columns>
having <having clause>
order by <columns>;
I think this is the query you are looking for:
select id
from (select distinct id
from student
order by id desc
) t
where rownum <= 2;
Oracle processes the rownum before the order by, so you need a subquery to get the first two rows. The min() was forcing an aggregation that returned only one result, but before the rownum was applied.
If you actually want only the second value, you need an additional layer of subqueries:
select min(id)
from (select id
from (select distinct id
from student
order by id desc
) t
where rownum <= 2
) t;
However, I would do:
select id
from (select id, dense_rank() over (order by id) as seqnum
from student
) t
where seqnum = 2;
Order asc instead of desc
select id from student where rownum <=2 order by id asc;
Why not just use
select id
from ( select distinct id
, row_number() over (order by id desc) x
from student
)
where x = 2
Or even really bad. Getting the count and index :)
select id
from ( select id
, row_number() over (order by id desc) idx
, sum(1) over (order by null) cnt
from student
group
by id
)
where idx = cnt - 1 -- get the pre-last
Or
where idx = cnt - 2 -- get the 2nd-last
Or
where idx = 3 -- get the 3rd
Try this
SELECT *
FROM (
SELECT id, row_number() over (order by id asc) row_num
FROM student
) AS T
WHERE row_num = 2 -- or 3 ... n
ROW_NUMBER

Select the 100 lowest values in SQL?

I've been looking around for a while, and it seems it cant be found anywhere. I want to know how do you select the 100 highest and the 100 lowst values in a column? The MIN-function only chooses the lowest one and the MAX the highest one.
Anyone out there who knows how you do this?
SQL Server
Top 100 Highest
SELECT TOP 100 * FROM MyTable
ORDER BY MyCol DESC
Top 100 Lowest
SELECT TOP 100 * FROM MyTable
ORDER BY MyCol ASC
MySQL
Top 100 Highest
SELECT * FROM MyTable
ORDER BY MyCol DESC LIMIT 100
Top 100 Lowest
SELECT * FROM MyTable
ORDER BY MyCol ASC LIMIT 100
You can do it as below,
Highest
select * from
tablename
order by
column DESC
limit 0,100
Lowest
select * from
tablename
order by
column ASC
limit 0,100
EDIT
For SQL Server replace select * from with select TOP 100 * from
The SELECT TOP clause is used to specify the number of records to return.
Use sorting in ascending and descending order and limit output to 100
if you use Sql server
you can order query desc and select top 1000 like :
select top(1000) * from mytable order by value desc
Try this:
DECLARE #V_MaxNo INT;
SELECT #V_MaxNo = COUNT(1) FROM TABLE_NAME WHERE (CONDITION_PART_AS_REQUIRED);
SELECT COLUMN_LIST
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [Order_by_column_list_with_ASC/DESC]) rowNo, COLUMN_LIST
FROM TABLE_NAME) A
WHERE (100 - rowNo) >= 0 or (#V_MaxNo - rowNo) < 100
Here's another approach independent from db engine
MAX
select * from MyTable a where 100 > (select count(id) from MyTable b where a.MyCol <= b.MyCol) order by MyCol desc

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;

Sql query to fetch 3rd lowest value

I have a table called employee_salary, having two columns(emp_id, emp_salary) in it.
I have a requirement to fetch 3rd lowest emp_salary from this table. In this case, what should be my query so that i can get the exact value.
I have tested this in Postgres Database. I hope this query work in all type of database. please try this.
SELECT
[emp_salary]
FROM [employee_salary]
GROUP BY [emp_salary]
ORDER BY [emp_salary] LIMIT 1 OFFSET 2;
This may be one solution
select top 1 * from
(
select top 3 * from
(
select distinct emp_sal from employee order by asc emp_sal
) d orderby desc emp_sal
)
SELECT TOP 1 * FROM employee_salary WHERE emp_salary in (SELECT TOP 3 emp_salary FROM employee_salary ORDER BY emp_salary) ORDER BY emp_salary DESC
However, this does not work in all DBs. You need to find out alternative. For eg. in Informix, the statement will be SELECT FIRST 1 *
Using windowing functions... this construct is for SQL Server:
;WITH CTE AS
(
SELECT ..., ROW_NUMBER() OVER (ORDER BY emp_salary) AS rn
FROM myTable
)
SELECT ...
FROM CTE
WHERE rn = 3
for identical salaries you can get using RANK () function in SQL Server
;WITH CTE AS
(
SELECT ..., RANK() OVER (ORDER BY emp_salary) AS rn
FROM myTable
)
SELECT ...
FROM CTE
WHERE rn = 3
I got the answer by executing the following query in sql server 2008
Select MIN(emp_salary) from MyTable Where emp_salary in
(Select DISTINCT TOP 3 emp_salary from MyTable order by 1 DESC)
I got the 3rd minimum value.
DISTINCT is used to when one or more salary are same.
select * from table_name where col_name = (select (min(col_name) from table_name where col_name > (select min(col_name) from table_name where col_name > (select min(col_name) from table_name)));
You need 3rd lowest Salary. Let dive deep in the question.
1st requirement is Need Salary , 2nd requirement is need lowest salary and 3rd requirement is 3rd Lowest Salary
SELECT * FROM employee_salary // "It will give us Salary"
ORDER BY emp_salary DESC //"It will show lowest salary on top"
LIMIT 2,1 // As wee need 3rd salary , i am saying LIMIT 2,1 skip first 2 and show 3rd one

Retrieving the second most highest value from a table

How do I retrieve the second highest value from a table?
select max(val) from table where val < (select max(val) form table)
In MySQL you could for instance use LIMIT 1, 1:
SELECT col FROM tbl ORDER BY col DESC LIMIT 1, 1
See the MySQL reference manual: SELECT Syntax).
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants (except when using prepared statements).
With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
select top 2 field_name from table_name order by field_name desc limit 1
SELECT E.lastname, E.salary FROM employees E
WHERE 2 = (SELECT COUNT(*) FROM employess E2
WHERE E2.salary > E.salary)
Taken from here
This works in almost all Dbs
Select Top 1 sq.ColumnToSelect
From
(Select Top 2 ColumnToSelect
From MyTable
Order by ColumnToSelect Desc
)sq
Order by sq.ColumnToSelect asc
Cool, this is almost like Code Golf.
Microsoft SQL Server 2005 and higher:
SELECT *
FROM (
SELECT
*,
row_number() OVER (ORDER BY var DESC) AS ranking
FROM table
) AS q
WHERE ranking = 2
Try this
SELECT * FROM
(SELECT empno, deptno, sal,
DENSE_RANK() OVER (PARTITION BY deptno ORDER BY sal DESC NULLS LAST) DENSE_RANK
FROM emp)
WHERE DENSE_RANK = 2;
This works in both Oracle and SQL Server.
Try this
SELECT TOP 1 Column FROM Table WHERE Column < (SELECT MAX(Column) FROM Table)
ORDER BY Column DESC
SELECT TOP 1 Column FROM (SELECT TOP <n> Column FROM Table ORDER BY Column DESC)
ORDER BY ASC
change the n to get the value of any position
Maybe:
SELECT * FROM table ORDER BY value DESC LIMIT 1, 1
one solution would be like this:
SELECT var FROM table ORDER BY var DESC LIMIT 1,1