How can I assign unique value to each duplicate value in a column in a table - sql

I have data in my table as below
Now I want to generate unique rank value to each duplicate value like 1,2,3,4 etc as below
How to do this in SQL Server 2016?

You seem to be looking for row_number():
select t.*,
row_number() over (partition by id, name order by deptid) as ranking
from t;

You can use DENSE_RANK as well,
select table.*,
DENSE_RANK() over (order by id, name ,deptid) as RANK
from table;

Related

How to concatenate rows when using with groupby based on a pattern in Microsoft SQL Server?

I have an example:
I want it to look like this:
Pretty much, there will be null cells following a value in the Amount Column. I want to concatenate the comment cells of those rows with null cells. I'm not sure how to do this. Is there a way to do this?
If there will be null cells following a value in the Amount Column (as you told in question) you can use ROW_NUMBER() to get unique number in cte and then calculating sum (order by new unique numbers) for every row (will be the same for one Amount).
And at last, using cte in FOR XML PATH().
--getting Sum as unique for every sequence (Amount and following values)
with cte AS
(
select Id,Amount,Number,sum(Amount)over(order by Number rows unbounded preceding)SumSeq,comment
from
(
select Id,Amount,comment,
row_number()over(order by Id)Number from Table
)x
)
select id,max(Amount),ConcatComments from
(
select id,SumSeq,Amount,
stuff((select Concat(',',comment)
from cte cte1 where cte1.SumSeq=cte2.SumSeq
for xml path('')),1,2,'') ConcatComments from cte cte2
)Z
group by SumSeq,id,ConcatComments
You can use the STRING_AGG function to concatenate the comments. Something like this:
Select ID, MAX(Amount) as Amount, STRING_AGG(Comment, ', ') as Comment
From [YourTable]
Group By ID;
Your data has no column specifying the ordering, but the results seem to depend on ordering. If you do have such a column, you can assign a grouping by counting the non-NULL values of amount for each id, and then aggregate. That would be:
select id, grp,
string_agg(comment, ', ') within group (order by <ordering column>) as comments
from (select t.*, count(amount) over (partition by id order by <ordering column>) as grp
from t
) t
group by id, grp;

Custom sorting in sql

I have a table with a column named category. the data in it is 1, 2, 3 so every row has a category.
I need sort data by category like this
1,2,3,1,2,3,1,2,3,....
then if some category finished sorting continues like this
1,2,3,1,2,3,1,3,1,3,1,1,1,1,....
I am using PostgreSQL.
thanks for your answers
You can use window functions:
order by row_number() over (partition by category order by category)
You can specify whatever you want for the order by. For instance, if you want a random ordering:
order by row_number() over (partition by category order by random())
You can use like this:
SELECT
c,
RANK () OVER (
ORDER BY c
) rank_number
FROM
ranks;
For more information: http://www.postgresqltutorial.com/postgresql-rank-function/
select ID from (
select *,row_number() over ( partition by id order by id ) rn from Yourtable
) I
order by rn,id

Distinct rows in a table in sql

I have a table with multiple rows of the same member id. I need only distinct rows based on 2 unique columns
Ex: there are 100 different customers, the table has 1000 rows because every customer has multiple cities and segments assigned to him.
I need 100 distinct rows for these customers depending on a unique segment and city combination. There is no specific requirement for this combination, just the first from the table is fine.
So, currently the table is somewhat like this,
Hope this helps.
use row_number()
select * from (select *,row_number() over(partition by memberid order by sales) rn
from table_name
) a where a.rn=1
Handy sql-server top(1) with ties syntax for that
select top(1) with ties t.*
from table_name t
order by row_number() over(partition by memberid order by sales)
As you have no paticular requirement for which exactly row to select, any column will do at order by, it can be null as well
select top(1) with ties t.*
from table_name t
order by row_number() over(partition by memberid order by (select null))
The simplest way to do this is to use the ROW_NUMBER() OVER(GROUP BY...) syntax. You have no need to use an order by, since you want an arbitrary row, but only one, for each member.
Since you need only the expected data, and not the Row_Number value, make sure that you detail the fields returned, like below:
SELECT
MemberId,
city,
segment,
sales
FROM (
SELECT *
ROW_NUMBER() OVER (GROUP BY MemberId) as Seq
FROM [Status]
) src
WHERE Seq = 1

Generate custom group ranking in sql

As posted, I am trying to generate group ranking based on Is_True_Mod column. Here Until next 1 comes, I want 1 group to be there. Please find expected output in SQL. Here in expected output, rows grouped based on Is_True_Mode column. Regular ranking showing for reference ( order by ranking should be their )
You can identify the groups using a cumulative sum. Then you can you row_number() to enumerate the rows:
select t.*,
row_number() over (partition by grp order by regularranking) as expected_output
from (select t.*,
sum(is_true_mode) over (order by regularranking) as grp
from t
) t;

Limit result set in sql window function

Assume I would like to rewrite the following aggregate query
select id, max(hittime)
from status
group by id
using an aggregate windowing function like
select id, max(hittime) over(partition by id order by hittime desc) from status
How can I specify, that I am only interested in the first result within the partition?
EDIT: I was thinking that there might be a solution with [ RANGE | ROWS ] BETWEEN frame_start AND frame_end. What to get not only max(hittime) but also the second, third ...
I think what you need is a ranking function, either ROW_NUMBER or DENSE_RANK depending on how you want to handle ties.
select id, hittime
from (
select id, hittime,
dense_rank() over(partition by id order by hittime desc) as ranking
from status
) as x
where ranking = 1; --to get max hittime
--where ranking <=2; --max and second largest
Use distinct statement.
select DISTINCT id, max(hittime) over(partition by id order by hittime desc) from status