Reputation: 191
I have a sql server table containing names:
Serial Name
1 Roger
2 John
3 John
4 Mike
5 Roger
6 John
7 Mike
I want to insert a UID column that will have unique IDs for unique names. So, it should look like,
Serial Name UID
1 Roger 1
2 John 2
3 John 2
4 Mike 3
5 Roger 1
6 John 2
7 Mike 3
Can anyone please help me with the query.
Upvotes: 1
Views: 2335
Reputation: 29677
First add the column to the table.
ALTER TABLE yourtable
ADD [UID] INT NULL;
ALTER TABLE yourtable
ADD constraint fk_yourtable_uid_id foreign key ([UID]) references yourtable([Serial]);
Then you can update the UID with the minimum Serial
ID per Name.
UPDATE t
SET [UID] = q.[UID]
FROM yourtable t
JOIN
(
SELECT Name, MIN([Serial]) AS [UID]
FROM yourtable
GROUP BY Name
) q ON q.Name = t.Name
WHERE (t.[UID] IS NULL OR t.[UID] != q.[UID]) -- Repeatability
Upvotes: 1
Reputation: 1271151
Simply use dense_rank()
:
select t.*, dense_rank() over (order by name) as unique_id
from t;
If you want to maintain the original ordering by the first column, then you can use that:
select t.*, min(serial) over (partition by name) as unique_id
from t;
This will have gaps. You can combine these to get a unique, gap-less sequence:
select t.*, dense_rank() over (order by seqnum) as unique_id
from (select t.*, min(serial) over (partition by name) as seqnum
from t
) t;
This method has the advantage that it is stable -- assuming that the first column is an identity column (so new names added over time would have higher serial
values than existing names).
Upvotes: 2
Reputation: 11205
To select it on the fly, use this:
with CTE as
(
select name, dense_rank() over (order by name) as rn
from MyTable
)
select t1.id, t1.name, t2.rn
from MyTable t1
inner join CTE t2
on t2.name = t1.name
To bake it in, create a new table of names with an identity(1,0)
column and add new names to this list (thrown together for inspiration)
create table name_uid
(
id int identity(1,0) not null,
name varchar(50)
)
insert into name_uid (name)
select distinct name
from mytable
alter table mytable
add the_uid int
alter table
add constraint fk_name_uid foreign key (the_uid) references name_uid(id)
update t1
set t1.the_uid = t2.id
from Mytable t1
inner join name_uid t2
on t1.name = t2.name
create trigger tr_uid on MyTable
for insert
as
declare @name varchar
declare @exist int
declare @uid int
begin
select @name = i.name from inserted i;
select @exist = case when exists (select 1 from name_uid where name = @name) then 1 else 0 end;
begin
if @exist = 0
insert into name_uid (name) values (@name);
end;
select @uid = select id from name_uid where name = @name;
update MyTable;
set the_uid = @uid;
go
Upvotes: 1