Select row based on max value in column SQL Server - sql

How can I get the output from the input using Microsoft SQL Server? (Basically select the row per ID where vote is max).
Input
ID Label Vote
-----------------------
79185673 2 3
79185673 0 17
79185724 4 5
79185724 1 13
79185724 0 2
79185900 1 17
79185900 2 1
79185900 4 2
79186190 3 3
79186190 2 17
Output
ID Label Vote
-----------------------
79185673 0 17
79185724 1 13
79185900 1 17
79186190 2 17

Use ROW_NUMBER or DENSE_RANK function to give a rank per ID in the descending order of Vote column and then select the rows having rank 1.
I prefer DENSE_RANK function, because it will give same rank for the same Vote values.
Query
;with cte as(
select [rank] = DENSE_RANK() over(
partition by [ID]
order by [Vote] desc
), *
from [your_table_name]
)
select [ID], [Label], [Vote] from cte
where [rank] = 1;

Related

MSSQL SELECT -get one result per group

I can't figure how to write a mssql select to solve this.
Example of a existing table data:
Id GroupID Pass
___ ________ _____
1 1 1
2 1 0
3 2 1
4 2 0
5 2 0
6 3 1
7 3 1
What i need is the following example (if one of Group is not passed, then 0 else 1):
GroupID Pass
________ _____
1 0
2 0
3 1
Thanks for your help!
Use MIN aggregation
SELECT groupid, MIN(pass)
FROM tablename
GROUP BY groupid
use window function row_number()
select GroupID,Pass from (
select *,
row_number() over(
partition by GroupID
order by Pass asc
) as [rn]
from [yourtable] as [t]
) as [t1]
where [rn] = 1;
Use MIN function with GROUP BY.
Query
select [GroupID], min([Pass]) as [Pass]
from [your_table_name]
group by [GroupID]
order by [GroupID];
And if the Pass column is in BIT type, then need to cast in to INT.

random row from diapason (1: n) in groups sql

I need select random row from Table using groups and order, but random's row number in group should not be more then constant (for example const = 3).
What I mean:
id time x
1 10:20 1
1 11:21 9
1 16:14 4
1 08:13 8
2 01:20 2
2 21:13 0
For id=1 rows could be:
id time x
1 10:20 1
1 11:21 9
1 08:13 8
BUT not
1 16:14 4 because in order by time it's local number more than 3
for
Id= 2 - any row
WITH cte as (
SELECT *, ROW_NUMBER() OVER (partition by id ORDER BY RANNDOM()) as rn
FROM myTable
)
SELECT *
FROM cte
WHERE rn <= 3
Something like this:
SELECT distinct on (id) *
FROM (select
row_number() over (partition by id order by time ) as up_lim
from tab1) as a
WHERE row_number <= 3
ORDER by id, random() ;

SQL query to find counts of numbers in running total

Suppose the table has 1 column ID and the values are as below:
ID
5
5
5
6
5
5
6
6
the output should be
ID count
5 3
6 1
5 2
6 2
How can we do that in a single SQL query.
If you want to find the Total count of the Records you have you can write like
select count(*) from database_name order by column_name;
In relational databases data in the table has no any order, see this: https://en.wikipedia.org/wiki/Table_(database)
the database system does not guarantee any ordering of the rows unless
an ORDER BY clause is specified in the SELECT statement that queries
the table.
therefore, in order to get desired results, you must have an additional colum in the table that defines an order of rows (and can by used in ORDER BY clause).
In the below examle cn column defines such an order:
select * from tab123 ORDER BY rn;
RN ID
---------- -------
1 5
2 5
3 5
4 6
5 5
6 5
7 6
8 6
Starting from Oracle version 12c new MATCH_REGOGNIZE clause can be used:
select * from tab123
match_recognize(
order by rn
measures
strt.id as id,
count(*) as cnt
one row per match
after match skip past last row
pattern( strt ss* )
define ss as ss.id = prev( ss.id )
);
On earlier versions that support windows function (Oracle 10 and above) you can use two windows functions: LAG ... over and SUM ... over, in this way
select max( id ) as id, count(*) as cnt
FROM (
select id, sum( xxx ) over (order by rn ) as yyy
from (
select t.*,
case lag( id ) over (order by rn )
when id then 0 else 1 end as xxx
from tab123 t
)
)
GROUP BY yyy
ORDER BY yyy;

Update Last Row as First row Value

I have table in below format
SeqID Control_ID Data_Value RowNum
1 SEARCH SEARCH 3
1 BROKERREF BZ815 4
1 SYSTEM 0 5
2 pdp pdp 1
2 test 123 2
2 system 235 3
I want to update the table to be in below format
SeqID Control_ID Data_Value RowNum
1 BROKERREF BZ815 4
1 SYSTEM 0 5
1 SEARCH SEARCH 3
2 test 123 2
2 system 235 3
2 pdp pdp 1
I need to select the top row as a last row for each group of sequence ID.
Note : Control_Id and DataValue Column name will be same for the row which need to be selected as a last row for each unique sequenceID
Thanks in advance.
Use ROW_NUMBER() to locate the first row per SeqID. Then, in an outer query, use CASE expression in the ORDER BY clause to place this row in the last
position within its partition:
SELECT SeqID, Control_ID, Data_Value, RowNum
FROM (
SELECT SeqID, Control_ID, Data_Value, RowNum,
ROW_NUMBER() OVER (PARTITION BY SeqID ORDER BY RowNum) AS rn
FROM mytable ) t
ORDER BY SeqID,
CASE WHEN t.rn = 1 THEN 1 ELSE 0 END,
RowNum
SQL Fiddle Demo

Remove minimum rank rows in SQL Server

I have a table like below.
Customer Order Rank
1 12 3
1 14 7
2 15 6
2 16 4
2 17 2
2 21 1
3 24 5
3 25 6
3 27 7
Now, I want to select all rows except for rows with minimum ranks for each customer. It should look like below.
Customer Order Rank
1 14 7
2 15 6
2 16 4
2 17 2
3 25 6
3 27 7
You can use a CTE + ROW_NUMBER:
WITH CTE AS
(
SELECT Customer, [Order], Rank,
RN = ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY Rank)
FROM dbo.Customers
)
SELECT Customer, [Order], Rank
FROM CTE
WHERE RN > 1
ORDER BY Customer, Rank DESC
Demo: http://sqlfiddle.com/#!6/444be/3/0
WITH CTE AS (
SELECT Customer,Order,Rank,
ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY Rank ) as rn FROM t
)
SELECT Customer,Order,Rank FROM CTE
WHERE rn >1