Рассчитать идентификатор столбца с помощью логики - PullRequest
3 голосов
/ 15 сентября 2010

Я хотел бы получить предложения, как решить следующее требование.

У меня есть таблица с тремя полями: EmployeeId, HireDate и DepartmentId.

Код сотрудника должен быть в следующем формате: yyyyddddxxxx где:

  yyyy - is the year the employee was hired.
  dddd - DepartmentId.
  xxxx - running number for each department on each year.

Будет ли это лучше всего вычисляться с использованием sql или C #? Как рассчитать часть «хххх»? При необходимости я могу добавить больше полей в таблицу.

Ответы [ 3 ]

1 голос
/ 15 сентября 2010

Чтобы упростить ваши запросы, вы можете сделать employeeId вычисляемым столбцом (который также может быть PRIMARY KEY в SQL Server).

Я бы предложил вам написать сохраненныйПроцедура добавления ваших сотрудников:

CREATE TABLE employee
        (
        employeeId AS
                RIGHT(REPLICATE('0', 4) + CAST(year AS VARCHAR), 4) +
                RIGHT(REPLICATE('0', 4) + CAST(dept AS VARCHAR), 4) +
                RIGHT(REPLICATE('0', 4) + CAST(id AS VARCHAR), 4) PERSISTED NOT NULL PRIMARY KEY,
        id INT NOT NULL,
        dept INT NOT NULL,
        year INT NOT NULL,
        CHECK (id BETWEEN 0 AND 9999),
        CHECK (dept BETWEEN 0 AND 9999),
        CHECK (year BETWEEN 0 AND 9999)
        )        
GO
CREATE PROCEDURE prcAddEmployee(@dept INT, @year INT, @employeeId VARCHAR OUT)
AS
        DECLARE @tt TABLE (employeeId VARCHAR(12))
        INSERT
        INTO    employee (id, dept, year)
        OUTPUT  INSERTED.employeeId
        INTO    @tt
        VALUES  (
                (
                SELECT  COALESCE(MAX(id), 0) + 1
                FROM    employee WITH (TABLOCK)
                WHERE   dept = @dept
                        AND year = @year
                ),
                @dept, @year
                )
        SELECT  @employeeId = employeeId
        FROM    @tt
GO        

Вот код для проверки:

DECLARE @employeeId VARCHAR(12)
EXEC prcAddEmployee 1, 2010, @employeeId
EXEC prcAddEmployee 1, 2010, @employeeId
EXEC prcAddEmployee 2, 2010, @employeeId
EXEC prcAddEmployee 2, 2010, @employeeId
EXEC prcAddEmployee 1, 2010, @employeeId

SELECT  *
FROM    employee
1 голос
/ 15 сентября 2010

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 для нового сотрудника в этом новом отделе в следующем году. *

0 голосов
/ 15 сентября 2010

Поскольку xxxx содержит только 4 числа, я не думаю, что эта функция интенсивно используется (я имею в виду 100 или более раз в секунду).Поэтому я не думаю, что вам нужно слишком сильно беспокоиться о блокировке и производительности.

Наилучшим подходом было бы создание отдельной таблицы, которая будет содержать последний номер и год.

Beочень осторожны при обновлении этой таблицы.Проверьте, обновлялся ли другой клиент между тем, когда вы его получили, и хотите обновить его.Используйте следующий синтаксис:

UPDATE xxxxTable
SET number = newNumber
WHERE year = @year and number = @oldnumber

Затем проверьте количество обновленных строк, если это не 1, вы должны создать новый номер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...