Reputation: 473
I want to update any duplicate string against a client and make it unique by appending a number at the end of it. Following is just a illustration of something that I have.
|Id|ClientId|String|
|1 |123 |Apple |
|2 |123 |Apple |
|3 |123 |Orange|
|4 |222 |Grapes|
|5 |222 |Grapes|
Due to the nature of data, I had to use the Row_Number() (which I am new to it) to achieve the following result. My question is how can I iterate through the following table and append a number against each client that has a duplicate string so that they are all unique.
|Id|ClientId|String|RowId|
|1 |123 |Apple |1 |
|2 |123 |Apple |2 |
|3 |123 |Orange|3 |
|4 |222 |Grapes|1 |
|5 |222 |Grapes|2 |
What I want the end result to look like
|Id|ClientId|String |RowId|
|1 |123 |Apple 1 |1 |
|2 |123 |Apple 2 |2 |
|3 |123 |Orange |3 |
|4 |222 |Grapes 1 |1 |
|5 |222 |Grapes 2 |2 |
If it helps following is my sql:
patternsWithNumbers AS
(
Select row_number() over (partition by ClientId + String order by Id asc) AS RowId,
id,
t1.*
from tableName t
inner join table 2 t2 on t2.ClientId = t1.ClientId and t2.String = t1.String
)
Upvotes: 2
Views: 7130
Reputation: 57
I would slightly modify Gordon's answer, so that first only product names are changed:
UPDATE t
SET
string = string + ' ' + CAST(t2.item_id AS VARCHAR(255))
FROM
(SELECT t.id,
ROW_NUMBER() OVER (PARTITION BY clientid, string ORDER BY id) AS item_id,
COUNT(*) OVER (PARTITION BY clientid, string) AS item_count
FROM t)
t2
INNER JOIN t
ON t.id = t2.id
WHERE t2.item_count > 1
Then it is easy to just to add item number for the client (of course in real life you possibly have also order_id or something like that, which is needed to included in both of these queries?):
UPDATE t
SET
RowId = row_id
FROM
(SELECT t.id,
ROW_NUMBER() OVER (PARTITION BY clientid ORDER BY id) AS row_id
FROM t)
t2
INNER JOIN t
ON t.id = t2.id
Upvotes: 0
Reputation: 1269843
The following query calculates rowid
:
select t.*,
(string +
(case when count(*) over (partition by clientid, string) > 1
then cast(row_number() over (partition by clientid, string order by id) as varchar(255))
else 0
end)
) as new_string,
row_number() over (partition by clientid, string order by id) as rowid
from t
Use an updatable CTE to change the table:
with toupdate as (
select t.*,
row_number() over (partition by clientid, string order by id) as new_rowid,
count(*) over (partition by clientid, string) as cnt
from t
)
update toupdate
set rowid = new_rowid,
string = string + cast(new_rowid as varchar(255))
where cnt > 1;
Upvotes: 0
Reputation: 17126
You can use your query in a CTE like below:
; with cte as
( select id,clientid,string,
row_number() over(partition by clientid, string order by id asc) r
from tbl)
select
c1.id,
c1.Clientid,
CONCAT(c1.String, case when c2.id is not null then cast(c1.r as varchar(100)) else null end),
c1.r
from cte c1
left join cte c2
on c2.r>1
and c1.string=c2.string
and c1.clientid=c2.clientid
order by id asc
Upvotes: 1