PostgreSQL Absolute Ranking - sql

The users table is like this:
Id
Name
Room
Point
1
A
1
10
2
B
1
20
3
C
2
30
4
D
2
40
I want to get ranking with some conditions.
The query is SELECT *, RANK() OVER (ORDER BY users.point ASC) rnk FROM users WHERE users.room = 2
Then the ranking column(rnk) is not a absolute ranking.
The query result is
Id
Name
Room
Point
rnk
3
C
2
30
1
4
D
2
40
2
But I want absolute ranking, and the expected result is
Id
Name
Room
Point
rnk
3
C
2
30
3
4
D
2
40
4

Rank first, filter later. For example:
select *
from (
select *, rank() over(order by point) as rnk
from users
) x
where room = 2

Related

SQL - group for every 2 records

Original Table:
id rank
A 1
B 1
D 2
E 2
G 3
H 3
I 4
J 5
K 6
L 6
M 7
Would like to add one more group column - the value will be + 1 every 2 record:
id rank group
A 1 1
B 1 1
D 2 1
E 2 1
G 3 2
H 3 2
I 4 2
J 5 3
K 6 3
L 6 3
M 7 4
What I can think is only able to hardcode a "case when" condition for ranking. Since the table could be large, is there another function that can group the record dynamically?
Case when rank >0 and rank <=2 then 1 When rank >2 and rank <=4 then 2 When rank >4 and rank <=6 then 3 end group ....
Using ceil() function would be a direct option after dividing rate column by 2 :
SELECT id, rank, ceil( rank / 2 ) as "group"
FROM tab;
Btw, I replaced group with "group" since it is a reserved keyword
This is achievable using dense_rank()
select dense_rank() over (partition by rank % 2 order by id) as grouping, rank
from tableA
order by rank

SQL query to find the entries corresponding to the maximum count of each type

I have a table X in Postgres with the following entries
A B C
2 3 1
3 3 1
0 4 1
1 4 1
2 4 1
3 4 1
0 5 1
1 5 1
2 5 1
3 5 1
0 2 2
1 2 3
I would like to find out the entries having maximum of Column C for every kind of A and B i.e (group by B) with the most efficient query possible and return corresponding A and B.
Expected Output:
A B C
1 2 3
2 3 1
0 4 1
0 5 1
Please help me with this problem . Thank you
demo: db<>fiddle
Using DISTINCT ON:
SELECT DISTINCT ON (B)
A, B, C
FROM
my_table
ORDER BY B, C DESC, A
DISTINCT ON gives you exactly the first row for an ordered group. In this case B is grouped.
After ordering B (which is necessary): We first order the maximum C (with DESC) to the top of each group. Then (if there are tied MAX(C) values) we order the A to get the minimum A to the top.
Seems like it is a greatest n per group problem:
WITH cte AS (
SELECT *, RANK() OVER (PARTITION BY B ORDER BY C DESC, A ASC) AS rnk
FROM t
)
SELECT *
FROM cte
WHERE rnk = 1
You're not clear which A needs to be considered, the above returns the row with smallest A.
itseems to me you need max()
select A,B, max(c) from table_name
group by A,B
this will work:
select * from (SELECT t.*,
rank() OVER (PARTITION BY A,B order by C) rank
FROM tablename t)
where rank=1 ;

SQL query to take top elements of ordered list on Apache Hive

I have the table below in an SQL database.
user rating
1 10
1 7
1 6
1 2
2 8
2 3
2 2
2 2
I would like to keep only the best two ratings by user to get:
user rating
1 10
1 7
2 8
2 3
What would be the SQL query to do that? I am not sure how to do it.
It will work
;with cte as
(select user,rating, row_number() over (partition by user order by rating desc) maxval
from yourtable)
select user,rating
from cte
where maxval in (1,2)

How to select a random row when 2 rows have an equal property

I have a table containing items in a priority order as such:
id priority
1 1
2 2
3 3
4 8
5 3
6 4
Currently I retrieve items (SQL Server) in priority order, although a random item when there are matching priorities using the following query:
select item
from table
order by priority, newid()
This will return
id priority
1 1
2 2
3 3
5 3
6 4
4 8
or
id priority
1 1
2 2
5 3
3 3
6 4
4 8
So it's approximately 50/50 traffic
I now have a requirement to only retrieve one row of the rows when there are two matching priorities, for example..
id priority
1 1
2 2
3 3
6 4
4 8
or
id priority
1 1
2 2
5 3
6 4
4 8
You can use ROW_NUMBER, presuming SQL-Server (because of NEWID):
WITH CTE AS
(
SELECT t.*, RN = ROW_NUMBER() OVER (PARTITION BY Priority
ORDER BY ID)
FROM dbo.table t
)
SELECT * FROM CTE WHERE RN = 1
If these are all columns you could also use this sql:
SELECT MIN(t.ID) AS ID, t.Priority
FROM dbo.table t
GROUP BY t.priority
Update "No, I need to be able to get a random row when two (or more) priorities match"
Then i have misunderstood your requirement. You can use ORDER BY NEWID:
WITH CTE AS
(
SELECT t.*, RN = ROW_NUMBER() OVER (PARTITION BY Priority
ORDER BY NEWID())
FROM dbo.table t
)
SELECT * FROM CTE WHERE RN = 1

Increment Row Number on Group

I am working on a query for SQL Server 2005 that needs to return data with two 'index' fields. The first index 't_index' should increment every time the 'shade' column changes, whilst the second index increments within the partition of the values in the 'shade' column:
t_index s_index shade
1 1 A
1 2 A
1 3 A
1 4 A
1 5 A
2 1 B
2 2 B
2 3 B
2 4 B
2 5 B
To get the s_index column I am using the following:
Select ROW_NUMBER() OVER(PARTITION BY [shade] ORDER BY [shade]) as s_index
My question is how to get the first index to only increment when the value in the 'shade' column changes?
That can be accomplished with the DENSE_RANK() function:
DENSE_RANK() OVER(Order By [shade]) as t_index
You can try to use DENSE_RANK() for that:
SELECT
shade,
s_index = ROW_NUMBER() OVER(PARTITION BY [shade] ORDER BY [shade]),
t_index = DENSE_RANK() OVER (ORDER BY [shade])
FROM dbo.YourTableNameHEre
Gives output:
shade s_index t_index
A 1 1
A 2 1
A 3 1
A 4 1
A 5 1
B 1 2
B 2 2
B 3 2
B 4 2
B 5 2