I have the following table:
id a b
1 1 kate
1 4 null
1 3 paul
1 3 paul
1 2 lola
2 1 kim
2 9 null
2 2 null
In result it should be this:
1 3 paul
2 1 kim
I want to get the last a where b is not null. Something like:
select b
from (select,b
row_num() over (partition by id order by a desc) as num) as f
where num = 1
But this way I get a null value, because to the last a = 4 corresponds to b IS NULL. Maybe there is a way to rewrite ffill method from pandas?
Assuming:
a is defined NOT NULL.
You want the row with the greatest a where b IS NOT NULL - per id.
SELECT DISTINCT ON (id) *
FROM tbl
WHERE b IS NOT NULL
ORDER BY id, a DESC;
db<>fiddle here
Detailed explanation:
Select first row in each GROUP BY group?
Try:
select id, a, b
from (select id, a, b,
row_num() over (partition by id order by a desc nulls last) as num
from unnamedTable) t
where num = 1
Or, if that isn't right, try it with nulls first. I can never remember which way it works with desc.
If you aren't guaranteed to have at least one non-null per id then you'll want to move nulls to the bottom of the list rather than filtering those rows out entirely.
select id, a, b
from (
select id, a, b,
row_number() over (
partition by id
order by case when b is not null then 0 else 1 end, a desc
) as num
) as f
where num = 1
You can wrap this around a cte and join it back to the main table if you wish to keep the original columns as is, but looking at your expected output and logic, this should do it. Having said that, row_number() based approach might be a tad faster.
select distinct
id,
max(a) over (partition by id) as a,
first_value(b) over (partition by id order by a desc) as b
from tbl
where b is not null;
Related
I have a table like below in SQL Server. I reach the row number values with using ROW_NUMBER partition function. But this was not the result I wanted to achieve.
RowNumber
Value
1
A
2
A
3
A
1
B
2
B
1
C
1
D
I want to get this table
RowNumber
Value
1
A
1
A
1
A
2
B
2
B
3
C
4
D
How can I do it, do you have a function suggestion?
Use DENSE_RANK instead of ROW_NUMBER
SELECT DENSE_RANK() OVER (ORDER BY VALUE), VALUE
FROM TABLE
Use DENSE_RANK:
SELECT DENSE_RANK() OVER (ORDER BY Value) RowNumber, Value
FROM yourTable
ORDER BY 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;
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 ;
I have a table like this in SQL server 2014:
name
a
a
b
b
b
c
d
d
d
I want to create another column that is S.No. , but serial number value will be assigned according to name column. If name occurs 2 times the value of s.no. will be 1 and 2.If d is 3 times than value for d will be 1,2 and 3 and than again counter will start with 1 for e. so the table will be like:
name S.no.
a 1
a 2
b 1
b 2
b 3
c 1
d 1
d 2
d 3
Any solution? thanks for the help.
Use ROW_NUMBER():
SELECT name, ROW_NUMBER() OVER (PARTITION BY name ORDER BY (SELECT 1)) [S.no.]
FROM T
Just in another way by using Count()
select
Name,
Count(1) over (partition by Name ORDER BY Name ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as Slno
from MyTable
I've been trying to find a solution for this SQL query:
|A| |B| |Output|
===========================
1 A 1
1 A 1
1 B 2
1 C 3
2 C 1
2 D 2
2 F 3
2 H 4
3 D 1
3 D 1
3 I 2
As you can see, I want to create a column (output) that identifies, not counts or sums, the occurrence of each (A,B) tuple, without removing repeated occurences.
How would you do that?
Thanks in advance
Look up SQL Server Built-in DENSE_RANK() function.
SELECT *
,DENSE_RANK() OVER (PARTITION BY [A] ORDER BY [B] ASC) AS [OutPut]
FROM TableName
I think you want dense_rank():
select t.*,
dense_rank() over (partition by a order by b)
from table t;