SQL - group for every 2 records - sql

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

Related

PostgreSQL Absolute Ranking

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

SQL rank calculation by row

I have a table
Name
count
rank
A
2
1
A
4
2
A
7
3
I am trying to calculate new column D for the count with rank
for rank 1, count = 2
for rank 2, count = 4-2 =2
for rank 3, count = 7-2 -4 =1
The expected result should be
Name
count
rank
D
A
2
1
2
A
4
2
2
A
7
3
1
I am trying to use patrion by but it's not working
Use SUM() window function:
SELECT *,
2 * count - SUM(count) OVER (ORDER BY rank) D
FROM tablename;
See the demo.

Can you rearrange rows in sql tables accodring to a custom logic?

So I've been trying to change the order of rows according to my own logic.
Let's say I have a set of numbers from 1 to 4. If the rows have n entries of different values from 1 to 4 and I want to rearrange all the rows such that I have only rows with 4 at the top followed by a grouped combination of two 2's and a 1, followed by the 3's.
How can it be done using Sql server?
ID ROWS --> ID NEW ORDER
-- ---- -- ---------
A 1 G 4
B 1 G 4
C 2 G 4
C 2 G 4
D 2 C 2
D 2 C 2
E 2 A 1
E 2 E 2
F 3 E 2
F 3 B 1
F 3 D 2
G 4 D 2
G 4 F 3
G 4 F 3
G 4 F 3
Code till now:
SELECT * FROM table
ORDER BY
CASE
WHEN ROW = 4 THEN '1'
WHEN ROW = 1 THEN '2'
WHEN ROW = 2 THEN '3'
WHEN ROW = 3 THEN '4'
END ASC
Assuming ROWS is exactly the number of rows with a paticular ID,
order the rows first by a group according to ROWS interval (4),(1..2), (all the rest) then within the second group row_number() sequences of IDs having ROWS = 1 and 2 independently. Within the same sequence number order by ROWS reverse order.
select ID, ROWS
from (
select *
, case when ROWS = 4 then 1
when ROWS between 1 and 2 then 2
else 3 end grp1
, row_number() over(partition by ROWS order by ROWS) - row_number() over(partition by ROWS, ID order by ID) pos2
from yourtable) t
order by grp1, case ROWS when 1 then pos2 else pos2/2 end, -ROWS, ID
If you want you can try doing it using order by clause. You can use your logic to sort values accordingly. Default order by ASC. So i have tried below query with order by if this gives you some idea of doing it:
select id from test order by case when id%2 = 0 then id end desc
Will give;
ID
8
6
4
5
So you can try ordering with some logic inside.

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 ;

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