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

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.

Related

SQL reset row_number when previous id column null

This is hard to explain so I will give an example.
I need SQL (ms server), I assume its with row_number over partition but can't get it to work.
I have this table:
ID
PreviousID
Data
1
a
2
1
b
3
2
c
4
d
5
4
e
6
f
I want these results:
ID
NewID
Data
1
1
a
2
1
b
3
1
c
4
2
d
5
2
e
6
3
f
And another with just the new IDs of each sequence:
NewID
Data
1
a
2
d
3
f
Instead of a row number new id, it could also have the first id of the sequence, whatever is easier, as long as it identifies the sequence.
Seems you want a windowed COUNT of rows where the value of PreviousID is NULL.
SELECT ID,
COUNT(CASE WHEN PreviousID IS NULL THEN 1 END) OVER (ORDER BY ID) AS NewID,
Data
FROM dbo.YourTable;

Finding adjacent column values from the last non-null value of a certain column in Snowflake (SQL) using partition by

Say I have the following table:
ID
T
R
1
2
1
3
Y
1
4
1
5
1
6
Y
1
7
I would like to add a column which equals the value from column T based on the last non-null value from column R. This means the following:
ID
T
R
GOAL
1
2
1
3
Y
1
4
Y
3
1
5
4
1
6
Y
4
1
7
6
I do have many ID's so I need to make use of the OVER (PARTITION BY ...) clause. Also, if possible, I would like to use a single statement, like
SELECT *
, GOAL
FROM TABLE
So without any extra select statement.
T is in ascending order so just null it out according to R and take the maximum looking backward.
select *,
max(case when R is not null then T end)
over (
partition by id
order by T
rows between unbounded preceding and 1 preceding
) as GOAL
from TBL
http://sqlfiddle.com/#!18/c927a5/5

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 ;

How to ignore certain similar rows when select

I have the following table
Id col1 col2 col3
1 c 2 m
2 c 3 6
2 b d u
3 e 6 9
4 1 v 8
4 2 b t
4 4 5 g
As you can see, there are duplicate value in id column, 2 and 4. I only want to select rows with unique id value and ignore the following rows with duplicate id value. I just want to keep the first of the rows with duplicate values
1 c 2 m
2 c 3 6
3 e 6 9
4 1 v 8
There is FK constraint, so I cannot delete rows with duplicate values.
I am using SQL SERVER 2008 R2
Any reply will be appreciated.
You can use row_number to number each row with the same id. Then you can select only the first row per id:
select *
from (
select row_number() over (partition by id order by col1, col2, col3) rn
from YourTable
) as SubQueryAlias
where rn = 1
The subquery is required because SQL Server doesn't allow row_number directly in the where clause.