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

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;

Related

Finding Difficulty in getting maximum value

V_ABC(its a View)
ID value interest Reference Code
1 5 Fixed 2
1 2 Variable 4
2 6 Variable 5
2 2 Fixed 1
3 4 Fixed 5
3 1 Variable 4
i need this OutPut please.
ID value Interest Reference Code
1 7 Fixed 4
2 8 Variable 5
3 5 Fixed 5
I have a view V_ABC. I am trying to add value which is fine and also getting Max reference Code.
On Top, iIam trying to get interest type which based on maximum value but failed so far. e.g in view,
ID 1 has maximum value 5 and need Interest Fixed
ID 2 maximum value 6 and interest should be Variable
ID 3 maximum value 4 and interest should be fixed .
I am trying to get interest. Here is my SCRIPT. I am using SQL server 2016
Select id,sum(value),Max(ReferenceCode)
(
Select id,value,
first_value(Interest) over (Partition by value Order by value desc) as Interest,Referencecode From V_ABC
)dd
group by id
Probably the simplest method uses row_number() and conditional aggregation:
select id, sum(value),
max(case when seqnum = 1 then interest end),
max(case when seqnum = 1 then reference_code end)
from (select t.*,
row_number() over (partition by id order by value desc) as seqnum
from t
) t
group by id;
If you want to be fancy, you can use select distinct with window functions:
select distinct id,
sum(value) over (partition by id),
first_value(interest) over (partition by id order by value desc),
first_value(reference_code) over (partition by id order by value desc)
from t;

How to find the most frequently repeated column?

ID UserID LevelID
1 1 1
2 1 2
3 1 2
4 1 2
5 2 1
6 2 3
7 3 2
8 4 1
9 4 1
The query should return: LevelID: 1 (3 times) - the LevelID column that is most frequently repeated by different Users (UserID).
I have the following query:
SELECT LevelID, COUNT(LevelID) AS 'Occurrence'
FROM
(
SELECT DISTINCT * FROM
(
SELECT UserID, LevelID
FROM SampleTable
) cv
) levels
GROUP BY LevelID
ORDER BY 'Occurrence' DESC
Which returns:
LevelID Occurence
1 3
2 2
3 1
But it doesn't let me to add LIMIT 1; at the bottom to retrieve the first top row of the selection. What's wrong with the query?
There is no need for these several levels of nesting. Consider using aggregation, count(distinct ...), ordering the results and using a row-limiting clause to keep the top record only:
select top(1) levelID, count(distinct userID) cnt
from mytable
group by levelID
order by cnt desc
If you want to allow possible top ties, then use top (1) with ties instead of just top (1).

Calculate "position in run" in SQL

I have a table of consecutive ids (integers, 1 ... n), and values (integers), like this:
Input Table:
id value
-- -----
1 1
2 1
3 2
4 3
5 1
6 1
7 1
Going down the table i.e. in order of increasing id, I want to count how many times in a row the same value has been seen consecutively, i.e. the position in a run:
Output Table:
id value position in run
-- ----- ---------------
1 1 1
2 1 2
3 2 1
4 3 1
5 1 1
6 1 2
7 1 3
Any ideas? I've searched for a combination of windowing functions including lead and lag, but can't come up with it. Note that the same value can appear in the value column as part of different runs, so partitioning by value may not help solve this. I'm on Hive 1.2.
One way is to use a difference of row numbers approach to classify consecutive same values into one group. Then a row number function to get the desired positions in each group.
Query to assign groups (Running this will help you understand how the groups are assigned.)
select t.*
,row_number() over(order by id) - row_number() over(partition by value order by id) as rnum_diff
from tbl t
Final Query using row_number to get positions in each group assigned with the above query.
select id,value,row_number() over(partition by value,rnum_diff order by id) as pos_in_grp
from (select t.*
,row_number() over(order by id) - row_number() over(partition by value order by id) as rnum_diff
from tbl t
) t

SQL Get highest repeating value for a group clause

I want a SQL query which should tell me that for each ID which value repeated most of time.
For example lets take the following table:
Id Value
1 10
1 20
1 10
1 10
2 1
1 3
Desired Output
Id Value Count
1 10 3
2 1 1
From above example, it shows that for Id 1, Value 10 was repeated most of times and for Id 2, value 1 was repeated most of times
Any suggestion would be really appreciated.
Use rank to number the id's based on their value counts in descending order and pick up the 1st ranked rows.
select id, value, cnt
from (select id, value, count(*) as cnt,
rank() over (partition by id order by count(*) desc) as rnk
from t
group by id, value) x
where rnk = 1
Based on Gordon's comment, if you need only one value per id in case of ties, use row_number instead of rank, as rank returns all the ties in value counts.

SQL MAX(column) With Additional Criteria

I have a single table, where I want to return a list of the MAX(id) GROUPed by another identifier. However I have a third column that, when it meets a certain criteria, "trumps" rows that don't meet that criteria.
Probably easier to explain with an example. Sample table has:
UniqueId (int)
GroupId (int)
IsPriority (bit)
Raw data:
UniqueId GroupId IsPriority
-----------------------------------
1 1 F
2 1 F
3 1 F
4 1 F
5 1 F
6 2 T
7 2 T
8 2 F
9 2 F
10 2 F
So, because no row in groupId 1 has IsPriority set, we return the highest UniqueId (5). Since groupId 2 has rows with IsPriority set, we return the highest UniqueId with that value (7).
So output would be:
5
7
I can think of ways to brute force this, but I am looking to see if I can do this in a single query.
SQL Fiddle Demo
WITH T
AS (SELECT *,
ROW_NUMBER() OVER (PARTITION BY GroupId
ORDER BY IsPriority DESC, UniqueId DESC ) AS RN
FROM YourTable)
SELECT UniqueId,
GroupId,
IsPriority
FROM T
WHERE RN = 1