Функция SQL Server для анализа номеров записей - PullRequest
0 голосов
/ 29 сентября 2019

В нашей базе данных в таблице Cases в поле Docket хранятся номера (ы) docket для каждого случая.Каждый номер докета принимает форму, такую ​​как

  • AB19-1-000
  • CD19-1043-000
  • EF18-24-001

Они состоят из «корневых» и «вспомогательных».Корни здесь

  • AB19-1
  • CD19-1043
  • EF18-24

Корневые карманы состоят издвух буквенный префикс префикса, который указывает тип регистра.Затем следует двухзначный код символа, указывающий финансовый год, в котором было подано дело.Затем дефис.Затем «порядковый» номер (без фиксированного количества цифр, хотя ни в одной из них не было больше 4 цифр), указывающий последовательность, в которой было подано дело (по сравнению с другими делами того же типа, которые были поданы в этом финансовом году).

Последние три цифры (после последнего дефиса) общего номера подсчета представляют «поддокет» и должны учитывать несколько заявок в этом списке.Первоначальная подача всегда сопровождается поддокетом 000.Последующие записи в этом корневом докете подразделяются на 001, 002, 003 и т. Д.

Чтобы сделать вещи более сложными, в поле Docket может быть указано несколько номеров документов, и (в ужасном унаследованном проекте базы данных мыиметь) несколько номеров дочек всегда разделены ровно одним пробелом.(Я знаю. Не начинайте.)

Я хочу создать инструмент, который поможет нам генерировать номер списка для новых случаев проще / быстрее, чем наш текущий подход (который использует цикл VBA и являетсяочень медленно).В частности, я хочу написать функцию для использования на SQL Server, которая будет выдавать следующий порядковый номер для новой подачи данного типа и финансового года.

Шаги будут примерно:

  1. Принимайте в качестве аргумента двухсимвольный тип регистра и двухзначный финансовый год.
  2. Идентифицируйте все введенные номера досье, где префикс альфа - это указанный тип регистра, а следующие два символа - указанный финансовый год.(игнорируя поддокет, который нас здесь не волнует).
  3. Идентифицирует наивысший существующий порядковый номер для этого типа дела и года подсчета.
  4. Добавьте один к указанному номеру и верните эточисло.

Я неплохой программист, но мой SQL довольно ограничен довольно обычными запросами.У меня очень ограниченный опыт создания функций.Поэтому любая помощь (даже общая схема того, как эта функция может выглядеть и как ее создавать) очень ценится.

Вот некоторый код для генерации простых тестовых данных.

CREATE TABLE MyCases (
    CaseId   INTEGER       PRIMARY KEY,
    Docket   VARCHAR(50) not null
);

INSERT INTO MyCases 
VALUES 
(1, 'XL14-204-001 TS14-1-000 PI14-1-000'),
(2, 'PI14-2-000'),
(3, 'PI14-3-000'),
(4, 'PI14-4-001 XL14-22-000'),
(5, 'PI14-6-000'),
(6, 'PI14-7-000 XL14-382-000'),
(7, 'PI15-1-000 XL15-23-000'),
(8, 'PI15-2-000 TS15-23-000'),
(9, 'PI15-3-000'),
(10, 'PI15-4-000 TS15-2-000')
;

И с требуемой функцией, если пользователь введет MyFunction ('PI', 14), результат будет 8, потому что наибольшее существующее последовательное число для всех номеров досье PI14 равно PI14-7, а добавление одного к 7 дает 8Точно так же результат для MyFunction ('PI', 15) будет 5.

Ответы [ 2 ]

2 голосов
/ 29 сентября 2019

Примерно так:

create or alter function MyFunction(@RootDocket char(2), @FiscalYear smallint)
returns int as
begin
    declare @NextSequenceNumber int;

    with q as
    (
    select 
        c.CaseId, 
        cd.Docket,
        RootDocket = left(cd.Docket,2),
        FiscalYear = cast(right(left(cd.docket,4),2) as tinyint),
        SequenceNumber = cast(substring(cd.Docket,6, charindex('-',cd.Docket,7)-6) as smallint),
        SubDocket = cast(right(cd.Docket,3) as smallint)
    from dbo.mycases c
    cross apply (select value Docket from string_split(Docket,' ') ) cd(Docket)
    )
    select @NextSequenceNumber = max(SequenceNumber) + 1
    from q 
    where RootDocket = @RootDocket
      and FiscalYear = @FiscalYear

    return @NextSequenceNumber;
end
go 

select dbo.MyFunction('PI',15);
select dbo.MyFunction('PI',14);

выходы

-----------
5



-----------
8
1 голос
/ 29 сентября 2019

Вот подход, который использует цикл для последовательной проверки каждого возможного порядкового номера для данного типа дела и года.Как только найден доступный порядковый номер, он возвращается.

Это может быть немного более оптимизировано, чем то, что вы запрашивали, в том смысле, что оно заполнит пробелы в последовательности, если они есть.Это может или не может быть то, что вам нужно.

Код:

CREATE FUNCTION GetNextAvailableSequence (
    @case_type VARCHAR(2), 
    @fiscal_year INT 
)
RETURNS INT
AS
BEGIN

    DECLARE @seq INT;
    DECLARE @done INT;
    SET @done = 0;
    SET @seq = 0;

    WHILE @done = 0
    BEGIN
        SET @seq = @seq + 1;
        IF (
            SELECT COUNT(*) 
            FROM MyCases 
            WHERE ' ' + docket LIKE 
                '% ' 
                + @case_type
                + CAST(@fiscal_year as VARCHAR(2)) 
                + '-' 
                + CAST(@seq as VARCHAR(2)) 
                + '%'
        ) = 0
        BEGIN
            SET @done = 1;
       END;
    END;

    RETURN @seq;

END;

Демонстрация на DB Fiddle :

SELECT dbo.GetNextAvailableSequence('PI', 14);
| (No column name) |
| ---------------: |
|                5 |

Заполняет первый пробел для PI-14.

select dbo.GetNextAvailableSequence('PI', 15);
| (No column name) |
| ---------------: |
|                5 |

Для PI-15 пробелов нет, это первая доступная последовательность.

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