Get second max highest mark and name - sql

Consider a table with two columns: mark and name
I need to get the second highest value, and the name of the second highest value.

You can use ROW_NUMBER(), RANK(), DENSE_RANK() functions in SQL.
But in this case, you'll have to use DENSE_RANK() because there may be a condition where 2 or more students may have scored maximum marks, in such case you can't use ROW_NUMBER() or RANK().
Learn more about this functions click here
SELECT * FROM (
SELECT name, mark, DENSE_RANK() over (order by mark desc) RankNo
FROM tablename
) AS Result
WHERE Result.RankNo = 2

SELECT *
FROM (SELECT name,
mark,
Row_number() over(ORDER BY mark DESC) AS rownums
FROM employees)
WHERE rownums = 2;

SELECT name,mark FROM table ORDER BY mark desc limit 1,1
This code sort all records by mark in descending order. limit 1,1 skips the first result (first 1 = first record) and then returns the next result (second 1 = second record).

Related

Select 20 results per every column value

I prepared query that select date from table. In table I got: rank, name, citycode as columns. When I am doing something like that:
select name, citycode
from tab20
where rank <= 20
I got resault of first 20 rows that gets rank <= 20. And Everything would be ok, but I have to show results of first 20 rows per every citystate. Is it possible to create in one query ? I was tryin union etc but it doesn't work well.
Thanks
You would use the row_number() function. Based on the rank that would be:
select t.*
from (select t.*,
row_number() over (partition by citycode order by rank) as seqnum
from tab20 t
) t
where seqnum <= 20;

Multiple maximum values

So I am on SQLite and have the following table and need to print the two names to which correspond the highest number of wins(25). By using the MAX() function, I only get the first of the two rows. How is it possible to print both rows that have the maximum value for wins?
If you query this way, it will return the highest two rows.
SELECT
name,
Wins
FROM
table_name
ORDER BY Wins DESC
LIMIT 2;
Use RANK() window function:
SELECT name, Wins
FROM (
SELECT *, RANK() OVER(ORDER BY Wins DESC) rnk
FROM tablename
)
WHERE rnk = 1
This will return all the rows which will have the max number of Wins because all of them will be ranked as 1.
if you dont mind nested selects I think this should be getting all records have max wins
select name, wins from table where wins=(select max(wins) from table )
All names with top 2 score
WITH maxw (wins) AS(
SELECT DISTINCT wins
FROM tbl
ORDER BY wins DESC
LIMIT 2
)
SELECT tbl.*
FROM tbl
JOIN maxw ON tbl.wins = maxw.wins;

SQL query to select up to N records per criteria

I was wondering if it's possible to use SQL (preferably snowflake) to select up to N records given certain criteria.
To illustrate:
Lets say I have a table with 1 million records, containing full names and phone numbers.
There's no limits on the amount of phone numbers that can be assigned to X person, but I only want to select up to 10 numbers per person, even if the person has more than 10.
Notice I don't want to select just 10 records, I want the query to return every name in the table, I only want to ignore extra phone numbers when the person already has 10 of them.
Can this be done?
You can use window functions to solve this greatest-n-per-group problem:
select t.*
from (
select
t.*,
row_number() over(partition by name order by phone_number) rn
from mytable t
) t
where rn <= 10
Note that you need an ordering column to define what "top 10" actually means. I assumed phone_number, but you can change that to whatever suits your use case best.
Better yet: as commented by waldente, snowflake has the qualify syntax, which removes the need for a subquery:
select t.*
from mytable t
qualify row_number() over(partition by name order by phone_number) <= 10
This query will help your requirement:
select
full_name,
phonenumber
from
(select
full_name,
phonenumber,
ROW_NUMBER() over (partition by phonenumber order by full_name desc) as ROW_NUMBER from sample_tab) a
where
a.row_number between 1 and 10
order by
full_name asc,
phonenumber desc;
using Snowflake Qualify function:
select
full_name,
phonenumber
from
sample_tab qualify row_number() over (partition by phonenumber order by full_name) between 1 and 10
order by
full_name asc ,
phonenumber desc;

Selecting type(s) of account with 2nd maximum number of accounts

Suppose we have an accounts table along with the already given values
I want to find the type of account with second highest number of accounts. In this case, result should be 'FD'. In case their is a contention for second highest count I need all those types in the result.
I'm not getting any idea of how to do it. I've found numerous posts for finding second highest values, say salary, in a table. But not for second highest COUNT.
This can be done using cte's. Get the counts for each type as the first step. Then use dense_rank (to get multiple rows with same counts in case of ties) to get the rank of rows by type based on counts. Finally, select the second ranked row.
with counts as (
select type, count(*) cnt
from yourtable
group by type)
, ranks as (
select type, dense_rank() over(order by cnt desc) rnk
from counts)
select type
from ranks
where rnk = 2;
One option is to use row_number() (or dense_rank(), depending on what "second" means when there are ties):
select a.*
from (select a.type, count(*) as cnt,
row_number() over (order by count(*) desc) as seqnum
from accounta a
group by a.type
) a
where seqnum = 2;
In Oracle 12c+, you can use offset/fetch:
select a.type, count(*) as cnt
from accounta a
group by a.type
order by count(*) desc
offset 1
fetch first 1 row only

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