Magic!
;with Employees (EmployeeId, HireDate, DepartmentId) as
(
select 1, getdate()-10, 1 union
select 2, getdate()-10, 1 union
select 3, getdate()-8, 2 union
select 4, getdate()-7, 3 union
select 5, getdate()-6, 1
)
select cast(datepart(year, HireDate) as varchar(4)) +
right(replicate('0' ,4)+cast(DepartmentId as varchar(4)), 4) +
right(replicate('0' ,4)+cast(row_number() over (partition by DepartmentId,datepart(year, HireDate) order by HireDate asc) as varchar(4)), 4) EmployeeCode
,DepartmentId
,EmployeeId
,convert(varchar(10), HireDate, 120) HireDate
from Employees
даст нам следующее:
EmployeeCode DepartmentId EmployeeId HireDate
------------ ------------ ----------- ----------
201000010001 1 1 2010-09-05
201000010002 1 2 2010-09-05
201000010003 1 5 2010-09-09
201000020001 2 3 2010-09-07
201000030001 3 4 2010-09-08
UPDATE:
Теперь предположим, что вы хотите добавить нового сотрудника в Отдел №2 сегодня. Вот как я могу рассчитать новый код сотрудника для этого сотрудника:
declare @DepartmentId int
set @DepartmentId = 2
select
cast(datepart(year, getdate()) as varchar(4)) +
right(replicate('0' ,4)+cast(@DepartmentId as varchar(4)), 4) +
right(replicate('0' ,4)+cast(isnull(max(cast(right(EmployeeCode,4) as smallint)),0) + 1 as varchar(4)), 4) EmployeeCode
from dbo.Employees as e
where DepartmentId = @DepartmentId
and datepart(year, hiredate) = datepart(year, getdate())
UPDATE
Как видите, если вы добавите сотрудника в ранее существовавший отдел, скажем, # 200, то предложение max вернет ноль, поскольку в этом отделе нет сотрудников, и оно будет обнулено до 0 + 1, так что вы получите совершенно нормальный 201002000001
для этого сотрудника.
Предположим, прошел год, и теперь наступил 2011 год, и это последнее условие фильтрации снова обнуляет предложение max, и процедура повторяется, и мы получим 201102000001
для нового сотрудника в этом новом отделе в следующем году. *