Страницы

Поиск по вопросам

понедельник, 18 февраля 2019 г.

Написать сложно реализуемый алгоритм на Microsoft SQL Server

Здравствуйте.
Нужна помощь девелоперов с очень сильным алгоритмичным мышлением и опытом в SQL SERVER.
Имеем такую вот иерархию Account-ов
,
где Account_code - это, собственно, код аккаунта , Account_alias - название аккаунта, Hierarchy_level - позиция в иерархии. Это не вся таблица, в ней также присутствуют еще несколько Алиасов с уровнем в иерархии 0, 1 и т.д., всего больше 200 Алиасов с уровнем иерархии от 0 и выше (ссылку на полную таблицу смотри ниже).
На даный момент эта иерархия находится в БД, в таблице ACCOUNT_HIERARCHY. Нам же нужно переместить эту иерархию в другую таблицу, с такими колонками и содержимым:
ACC_CODE | ACC_ALIAS | HIER_LEVEL | PARENT_ID | CHILD_ID
CF-0000 |Cash Flow | 0 | NO P ID | CF - 0001
CF-0001 |Cash Fl Lev| 1 | CF-0000 | CF - 0028
и т.д. При этом, у одного предка может быть несколько детей, и, что самое важное, уровень иерархии может миновать ступень, как выделено на скриншоте (предок - 5 уровень, дети - сразу 7)
Вот ссылка на Excel файл - https://www.dropbox.com/s/ym5apeueajozzqw/%D0%9A%D0%BD%D0%B8%D0%B3%D0%B0.xlsx?dl=0
Я пробовал написать что то спомощью курсора и фетчей, но выходит одна ахинея из за отсутствия опыта. Буду безмерно благодарен за помощь.
UPDATE 1: Скрин с размещением таблицы в бд (лежит точно так же, как и в Excel файле)
UPDATE 2: В этой таблице лежит по сути 3 иерархии. Члены каждой иерархии идентифицируються с помощью значение с Account_Code, каждое из которых начинается с CF / CE / SP.
То есть, СF - 0000 с уровнем иерархии 0 - это начало иерархии CF,
CE - 0000 с уровнем иерархии 0 - это начало иерархии CE,
SP - 0000 с уровнем иерархии 0 - это начало иерархии SP.
UPDATE 3: Быть может, выйдет использовать что то в этом духе (начал писать, но застрял)
DECLARE @Account_code varchar(50) DECLARE @Account_alias varchar(255) DECLARE @Hierarchy_level int
DECLARE @Parent_account_id varchar(50) DECLARE @Child_account_id varchar(50)
DECLARE @Current_position varchar(50)
DECLARE c_account_hierarchy SCROLL CURSOR FOR SELECT ACCOUNT_CODE, ACCOUNT_NAME, HIERARCHY_LEVEL FROM RealEstate_RiskEngine_LDR.dbo.LDR_ACCOUNT_HIERARCHY
OPEN c_account_hierarchy
FETCH NEXT FROM c_account_hierarchy INTO @Account_code, @Account_alias, @Hierarchy_level
WHILE @@FETCH_STATUS = 0 BEGIN IF @Hierarchy_level = 0
INSERT INTO RealEstate_RiskEngine_DB.dbo.ACCOUNT_HIERARCHY(...) VALUES (...)


Ответ

Для начала надо обязательно добавить в таблицу колонку с возрастающей нумерацией строк, без нее SQL не гарантирует порядка строк, без которого невозможно правильно выстроить иерархию. Кроме того в запросе обязательно надо будет ссылаться на эти номера строк. В связи с этим в свой пример я ввел такую колонку и назвал ее num
Родительской записью является ближайшая запись, которая расположена до нее и у которой уровень иерархии меньше. Т.е. берем максимальный номер записи с меньшей иерархией, меньший текущего номера.
Потомком является запись, идущая непосредственно после данной, при условии, что её уровень иерархии больше. Это условие можно проверить с помощью функции lead()
select a.*, max(b.num) parent_id, case when lead(a.Hierarchy_level) over(order by a.num) > a.Hierarchy_level then lead(a.num) over(order by a.num) end child_id from accounts a left join accounts b on b.numСтарый пример на sqlfiddle.com (там все дико усложнено, сходу простейшее решение в голову не пришло) (P.S. из рубрики "не усложняйте себе жизнь" :) )

Комментариев нет:

Отправить комментарий