sequence Rank in query - sql-server

I would like to get sequence number in mssql. Please see below.
There is a table.
UserID Score TeamID
------------------------------
1 100 1
2 200 1
3 500 2
4 600 2
5 700 2
6 1000 3
I would like to sort by total score group by team. see below
RankID UserID Score TeamID TotalScore
-----------------------------------------------------------
1 3 500 2 1800
1 4 600 2 1800
1 5 700 2 1800
2 6 1000 3 1000
3 1 100 1 300
3 2 200 1 300
I want to code only one sql query. Help me someone how can I do this? Thanks.

This should work:
;WITH TotalScore AS (
SELECT UserID, Score, TeamID,
SUM(Score) OVER (PARTITION BY TeamID) AS TotalScore
FROM mytable
)
SELECT DENSE_RANK() OVER (ORDER BY TotalScore DESC) AS RankID,
UserID, Score, TeamID, TotalScore
FROM TotalScore
ORDER BY TotalScore DESC, Score
The Common Table Expression used calculates the total score per TeamID using windowed version of SUM. Using DENSE_RANK together with this calculated field we can easily generate the required RankID.

You can try this
SELECT
RANK() OVER(ORDER BY i.TotalScore DESC) AS RankID
,A.*
FROM
(
SELECT
UserID
,Score
,TeamID
,(SELECT SUM(Score) FROM yourTable tb2 WHERE tb2.TeamID = tb1.TeamID) AS TotalScore
FROM yourTable tb1
) A
ORDER BY A.TotalScore DESC

Have a Try with below,
Select DENSE_RANK() over(Order by (Select Sum(Score) from #tablename V where V.TeamID=T.TeamID ) desc )RankID
,*,
Sum(Score) over(Partition by TeamID) TotalScore from #tablename T
order by DENSE_RANK() over(Order by (Select Sum(Score) from #tablename V where V.TeamID=T.TeamID ) desc )
Dense Rank in the 'Order by' to sort the results by RANK Id and the same is used in Select statement, Subquery in the Dense Rank will rank based on the sum(Score) for a TeamID

Related

How to transpose min/max value to columns in SQL Server using Partition?

I want to get the MIN and MAX from a certain values and put them in columns beside each other. Here's my query but I don't know how to transpose the values...
SELECT *
, MIN([CID]) OVER (PARTITION BY [TID] ORDER BY [TID]) MinID
, MAX([CID]) OVER (PARTITION BY [TID] ORDER BY [TID]) MaxID
Given:
TID CID DATE
123456789 1 01JAN
123456789 2 02JAN
123456789 3 03JAN
123456789 4 04JAN
Result:
TID CID DATE MIN MAX DATEMIN DATEMAX
123456789 1 01JAN 1 4 01JAN 04JAN
Isn't simple aggregation good enough here?
select
tid,
min(cid) min_cid,
max(cid) max_cid,
min(date) min_date,
max(date) max_date
from mytable
group by tid
Or, if the cids and dates are not changing accordingly, you can use conditional aggregation:
select
tid,
max(case when rn_asc = 1 then cid end) cid_at_min_date,
max(case when rn_desc = 1 then cid end) cid_at_max_date,
min(date) min_date,
max(date) max_date
from (
select
t.*,
row_number() over(partition by tid order by cdate asc ) rn_asc,
row_number() over(partition by tid order by cdate desc) rn_desc
from mytable t
) t
where 1 in (rn_asc, rn_desc)
group by tid
This orders records by cdate, and gives you the cids that correspond to the minimum and maximum date. You can easily adapt the query if you want things the other way around (basically, switch cid and cdate).

Select a random row from each group SQL Server

I have a table like below
ID Code Age
----------------
1 4758 21
1 7842 14
1 9821 23
1 6842 9
2 8472 24
2 7558 31
2 7841 28
3 7881 38
3 8794 42
3 4871 43
For each ID, I want to select one of the rows at random like so
ID Code Age
----------------
1 7842 14
2 7841 28
3 4871 43
Is this possible in SQL Server?
select top 1 with ties id,code,age
from
table
order by row_number() over (partition by id order by rand())
Update: as per this Return rows in random order, you have to use NEWId,since RAND() is fixed for the duration of the SELECT on MS SQL Server.
select top 1 with ties id,code,age
from
table
order by row_number() over (partition by id order by NEWID())
Use Newid() in order by clause of Row_number()
SELECT [ID], [Code], [Age]
FROM (SELECT *,
Row_number()
OVER(
PARTITION BY ID
ORDER BY Newid()) RNO
FROM #Table1)A
WHERE RNO = 1
with cte as
(
select *,rank() over ( partition by id order by Newid()) as rn from #c
)
select id,code,age from cte where rn=1
To select different sets each time, use checksum(newid()) in the order by clause.
Query
;with cte as(
select *, rn = row_number() over(
partition by ID
order by abs(checksum(newid())) % 15
)
from [your_table_name]
)
select * from cte
where rn = 1;

SQL Server query should return max value records

I have table like this:
id_Seq_No emp_name Current_Property_value
-----------------------------------------------
1 John 100
2 Peter 200
3 Pollard 50
4 John 500
I want the max record value of particular employee.
For example, John has 2 records seq_no 1, 4. I want 4th seq_no Current_Property_Value in single query.
Select
max(id_Seq_No)
from
t1
where
emp_name = 'John'
To get the Current_Property_value, just order the results by id_Seq_No and get the first one:
SELECT
TOP 1 Current_Property_value
FROM
table
WHERE
emp_name = 'John'
ORDER BY
id_Seq_No DESC
this will give highest for all tied employees
select top 1 with ties
id_Seq_No,emp_name,Current_Property_value
from
table
order by
row_number() over (partition by emp_name order by Current_Property_value desc)
You can use ROW_NUMBER with CTE.
Query
;WITH CTE AS(
SELECT rn = ROW_NUMBER() OVER(
PARTITION BY emp_name
ORDER BY id_Seq_No DESC
), *
FROM your_table_name
WHERE emp_name = 'John'
)
SELECT * FROM CTE
WHERE rn = 1;

How to select last id(where id >0) fod each group in SQL Server 2008

I want to select last record of price column of my table where my value of column is greater than zero. How can I do that?
My stored procedure is :
SELECT
id, name, price
FROM
messages
WHERE
id IN (SELECT MAX(id)
FROM messages
WHERE price > 0
GROUP BY name)
The problem is that this code select max id that price is greater than zero not last id. Means select id=2 and id=6
But in last id of group (frank) price is zero but this stored procedure select id=2 while I want stored procedure select only id =6
id name price
--------------
1 frank 1000
2 frank 500
3 frank 0
4 john 200
5 john 100
6 john 20
There are multiple ways to approach this. Following your method, though, you just need to move the price comparison to the outer query:
SELECT id, name, price
FROM messages
WHERE price > 0 AND
id IN (SELECT MAX(id)
FROM messages
GROUP BY name
);
I would be more inclined to write this as:
select m.*
from (select m.*,
row_number() over (partition by name order by id desc) as seqnum
from messages m
) m
where seqnum = 1 and price > 0;
with cte as (
select row_number() over(partition by id order by id desc) rn,
id,name,price
from messages
)
select id,name,price
from cte
where rn=1 and price>0
Something like this.

how to to get first top 6 records indifferent columns T-sql?

I got a situation to display first top 6 records. first 3 records in FirstCol and next 3 in SecondCol. My query is like this:
select top 6 [EmpName]
from [Emp ]
order by [Salary] Desc
Result:
[EmpName]
----------------------
Sam
Pam
Oliver
Jam
Kim
Nixon
But I want the result to look like this:
FirstCol SecondCol
Sam Jam
Pam Kim
Oliver Nixon
; WITH TOP_3 AS
(
select TOP 3 [EmpName]
,ROW_NUMBER() OVER (ORDER BY [Salary] Desc) rn
from [Emp ]
order by [Salary] Desc
),
Other3 AS
(
SELECT [EmpName]
,ROW_NUMBER() OVER (ORDER BY [Salary] Desc) rn
FROM Employees
ORDER BY [Salary] DESC OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY
)
SELECT T3.[EmpName] , O3.[EmpName]
FROM TOP_3 T3 INNER JOIN Other3 O3
ON T3.RN = O3.RN
ORDER BY T3.RN ASC
You can do this using several windowing functions, this is kind of ugly but it will get you the result that you want:
;with data as
(
-- get your Top 6
select top 6 empname, salary
from emp
order by salary desc
),
buckets as
(
-- use NTILE to split the six rows into 2 buckets
select empname,
nt = ntile(2) over(order by salary desc),
salary
from data
)
select
FirstCol = max(case when nt = 1 then empname end),
SecondCol = max(case when nt = 2 then empname end)
from
(
-- create a row number for each item in the buckets to return multiple rows
select empname,
nt,
rn = row_number() over(partition by nt order by salary desc)
from buckets
) d
group by rn;
See SQL Fiddle with Demo. This uses the function NTILE, this takes your dataset of six rows and splits it into two buckets - 3 rows in bucket 1 and 3 rows in bucket 2. The (2) inside the NTILE is used to determine the number of buckets.
Next I used row_number() to create a unique value for each row within each bucket, this allows you to return multiple rows for each column.

Resources