Get specified row ranking number - sql

Here is the rows looks like:
Id Gold
1 200
2 100
3 300
4 900
5 800
6 1000
What I want to achieve is getting the rank number whose Id equals to 5, which is order by Gold descending.
So after ordering, the intermediate rows should be(NOT RETURN):
Id Gold
6 1000
4 900
5 800
And the SQL should just return 3, which is the ranking of Id = 5 row.
What is the most efficient way to achieve this?

You simply want top, I think:
select top 3 t.*
from t
order by gold desc;
If you want the ranking of id = 5:
select count(*)
from t
where t.gold >= (select t2.gold from t t2 where t2.id = 5);

Try This Code By using Dense_rank():
WITH cte
AS (SELECT *,
Dense_rank()
OVER(
ORDER BY [Gold] DESC) AS rank
FROM your_table)
SELECT rank
FROM cte
WHERE id = 5

Related

Find the top 2 records for each key in a table [duplicate]

This question already has an answer here:
PostgreSQL: top n entries per item in same table
(1 answer)
Closed 7 months ago.
I have a list of results of player's scores in games, and I need to get the first two finishers for each game. LIMIT 2 works for the result set as a whole, but I need to limit it to 2 (or 1 if there is only one) per game.
Table being queried:
game_id
player_id
score
1
10
100
1
20
300
1
30
200
2
40
100
2
50
200
Desired results:
game_id
player_id
score
1
20
300
1
30
200
2
50
200
2
40
100
Using RANK() we can try:
WITH cte AS (
SELECT *, RANK() OVER (PARTITION BY game_id ORDER BY score DESC) rnk
FROM yourTable
)
SELECT game_id, player_id, score
FROM cte
WHERE rnk <= 2
ORDER BY game_id, score DESC;
Note that if there be the possibility of ties, then you might want to use DENSE_RANK instead of RANK. If ties are not a concern, then you could also use ROW_NUMBER instead of RANK.

how to get row value with group by clause using subquery in PostgreSQL in Laravel 8?

This is my table, first I want to get status_exec of each MAX (date_sta) and after that I want to grouped by status_exec and get the COUNT.
id_out_sta
status_exec
date_sta
1
2
2021-11-07
1
1
2021-11-28
1
5
2021-12-07
2
7
2021-04-02
2
2
2021-05-12
2
6
2021-08-07
3
2
2021-08-05
3
5
2021-08-28
4
2
2021-03-15
4
5
2021-04-25
The result I would expect should be the following:
status_exec
COUNT
5
3
6
1
This is my query but it didn't help:
SELECT id_out_sta, status_exec , max(date_sta) as max_date_sta
FROM public.status_exe
join public.order_out on status_exe.id_out_sta = order_out.id_out
group by (id_out_sta);
Please any suggestion, query builder or simple query.
A common solution for this is row_number window function to find the maximum of each group. Using this in a CTE and then aggregating the result:
with s as (
select *,
Row_Number() over(partition by id_out_sta order by max_date_sta desc) rn
from t
)
select status_exec, Count(*) "Count"
from s
where rn=1
group by status_exec
Example DB<>Fiddle
Using DISTINCT ON followed by a subquery:
SELECT status_exec, COUNT(*) AS COUNT
FROM
(
SELECT DISTINCT ON (status_exec) *
FROM public.status_exe
ORDER BY status_exec, max_date_sta DESC
) t
GROUP BY status_exec;
Here is another example by using count window function.
SELECT * FROM (
SELECT DISTINCT ON (id_out_sta)
status_exec,
count(*) over(partition by status_exec)
FROM t
ORDER BY id_out_sta, max_date_sta DESC
) as list
GROUP BY 1,2
Fiddle is here

sql - select single ID for each group with the lowest value

Consider the following table:
ID GroupId Rank
1 1 1
2 1 2
3 1 1
4 2 10
5 2 1
6 3 1
7 4 5
I need an sql (for MS-SQL) select query selecting a single Id for each group with the lowest rank. Each group needs to only return a single ID, even if there are two with the same rank (as 1 and 2 do in the above table). I've tried to select the min value, but the requirement that only one be returned, and the value to be returned is the ID column, is throwing me.
Does anyone know how to do this?
Use row_number():
select t.*
from (select t.*,
row_number() over (partition by groupid order by rank) as seqnum
from t
) t
where seqnum = 1;

How to find the SQL medians for a grouping

I am working with SQL Server 2008
If I have a Table as such:
Code Value
-----------------------
4 240
4 299
4 210
2 NULL
2 3
6 30
6 80
6 10
4 240
2 30
How can I find the median AND group by the Code column please?
To get a resultset like this:
Code Median
-----------------------
4 240
2 16.5
6 30
I really like this solution for median, but unfortunately it doesn't include Group By:
https://stackoverflow.com/a/2026609/106227
The solution using rank works nicely when you have an odd number of members in each group, i.e. the median exists within the sample, where you have an even number of members the rank method will fall down, e.g.
1
2
3
4
The median here is 2.5 (i.e. half the group is smaller, and half the group is larger) but the rank method will return 3. To get around this you essentially need to take the top value from the bottom half of the group, and the bottom value of the top half of the group, and take an average of the two values.
WITH CTE AS
( SELECT Code,
Value,
[half1] = NTILE(2) OVER(PARTITION BY Code ORDER BY Value),
[half2] = NTILE(2) OVER(PARTITION BY Code ORDER BY Value DESC)
FROM T
WHERE Value IS NOT NULL
)
SELECT Code,
(MAX(CASE WHEN Half1 = 1 THEN Value END) +
MIN(CASE WHEN Half2 = 1 THEN Value END)) / 2.0
FROM CTE
GROUP BY Code;
Example on SQL Fiddle
In SQL Server 2012 you can use PERCENTILE_CONT
SELECT DISTINCT
Code,
Median = PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY Value) OVER(PARTITION BY Code)
FROM T;
Example on SQL Fiddle
SQL Server does not have a function to calculate medians, but you could use the ROW_NUMBER function like this:
WITH RankedTable AS (
SELECT Code, Value,
ROW_NUMBER() OVER (PARTITION BY Code ORDER BY VALUE) AS Rnk,
COUNT(*) OVER (PARTITION BY Code) AS Cnt
FROM MyTable
)
SELECT Code, Value
FROM RankedTable
WHERE Rnk = Cnt / 2 + 1
To elaborate a bit on this solution, consider the output of the RankedTable CTE:
Code Value Rnk Cnt
---------------------------
4 240 2 3 -- Median
4 299 3 3
4 210 1 3
2 NULL 1 2
2 3 2 2 -- Median
6 30 2 3 -- Median
6 80 3 3
6 10 1 3
Now from this result set, if you only return those rows where Rnk equals Cnt / 2 + 1 (integer division), you get only the rows with the median value for each group.

MAX function without group by

I have the following table:
ID | NUM
1 | 4
2 | 9
3 | 1
4 | 7
5 | 10
I want a result of:
ID | NUM
5 | 10
When I try to use MAX(NUM) I get and error that I have to use GROUP BY in order to use MAX function
Any idea?
As per the error, use of an aggregate like Max requires a Group By clause if there are any non-aggregated columns in the select list (In your case, you are trying to find the MAX(Num) and then return the value(s) associated in the ID column). In MS SQL Server you can get what you want via ordering and limiting the returned rows:
SELECT TOP 1 ID, NUM
FROM [table]
ORDER BY NUM DESC;
In other RDBMS systems the LIMIT offers similar functionality.
Edit
If you need to return all rows which have the same maximum, then use the WITH TIES qualification:
SELECT TOP 1 WITH TIES ID, NUM
FROM [table]
ORDER BY NUM DESC;
May return more than 1 result:
SELECT id, num
FROM table
WHERE num = (SELECT MAX(num) FROM table)
Try this query.
WITH result AS
(
select DENSE_RANK() OVER( ORDER BY NUM desc) AS RowNo,ID,NUM from #emp
)
select ID,NUM from result where RowNo=1
it will return max values even if it has more MAX values like:
ID | NUM
5 | 10
6 | 10
refer below link to know more about RANKING Functions:
http://msdn.microsoft.com/en-us/library/ms189798
How about:
SELECT TOP 1 ID,NUM FROM table ORDER BY NUM DESC;
Do this -
SELECT TOP 1 ID,
NUM
FROM <yourtable>
ORDER BY NUM DESC;
Get all rows have max values but THERE ARE 3 SELECT, It's not good for performance
SELECT id, MAX(num) as num
FROM table
GROUP BY id
ORDER BY MAX(num) DESC
LIMIT (SELECT COUNT(*)
FROM table
WHERE num =(SELECT MAX(num) FROM table)
)