Без справочников не обходится ни одна информационная система. Как правило, такие справочники представлены в виде одной либо нескольких таблиц, иногда связанных между собой. Одной из проблем является "неполнота" данных, когда справочник не заполнен по определенным позициям.
Необходимо разработать структуру справочника, который выдает значение "всегда", если нет значения в запрашиваемом узле справочника - должно быть выдано значение из вышестоящего уровня иерархии.
Пример подобной структуры:
|Id | ParentId | Name | Value | ,
где ParentId — ссылка на вышестоящий узел.
Глубина иерархии такого справочника не ограничена, так‑же возможно неограниченное разветвление дерева.
Рассмотрим справочник адресов почты сотрудников предприятия.
Id |
ParentId |
Name |
Value |
1 |
null |
Предприятие |
Наше предприятие |
2 |
1 |
factory@mail.ru |
Условный запрос вида Get({Предприятие=»Наше предприятие»}, E‑mail) выдаст значение «factory@mail.ru».
Добавим узел дерева справочника — Подразделение=»Отдел ИТ» и к нему еще один узел
E‑mail=”it@mail.ru”
Теперь запрос Get({Предприятие=»Наше предприятие», Подразделение=»Отдел ИТ»}, E‑mail) выдаст значение «it@mail.ru». Однако, если нет узла «Подразделение», либо значение не заполнено — значение будет взято из вышестоящего узла.
Если добавить узел дерева «Служба поддержки» и значение support@mail.ru со ссылкой на узел «Подразделение»=»Отдел ИТ» — получим адрес службы поддержки, если он не существует — адрес отдела, и так далее выше по иерархии.
Таким образом получаем структуру справочника, который выдает значение «всегда».
Второй пример — интернационализация приложения.
Для интернационализации приложения предлагается следующий подход:
в базе данных хранятся значения Caption и Hint для всех компонентов, используемых в приложении;
при запуске приложения они считываются из БД и заполняются соответствующие свойства компонентов;
для получения значения Caption и Hint запрос к БД делается в виде: Application.Form.Component.Property.Origin;
для хранения Caption и Hint используется иерархическая структура справочника, который выдает значение «всегда», если нет значения в запрашиваемом узле справочник — будет выдано значение из вышестоящего уровня иерархии. Глубина иерархии такого справочника не ограничена, так‑же возможно неограниченное разветвление дерева.
Пример: Запрос Get(Application.Form1.Component2.Property3) выдаст значение из узла «Application», если нет значений для нижестоящего уровня иерархии, выдаст значение из узла «Form1» — если есть значение для этого уровня иерархии, и так далее.
Таким образом можно, например, ввести значение Caption=»Поиск» для кнопки с Origin=»Find» для всего приложения, но для кнопки на форме «Form2» — использовать значение «Искать», а для кнопки «btnFindAll» — - использовать значение «Искать везде».
Такой способ существенно экономит место в БД, так как хранится всего одно общее значение и исключения от него.
Структура таблицы:
CREATE TABLE t_caption_ru (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INT NULL DEFAULT '0',
owner VARCHAR(255) NOT NULL,
origin VARCHAR(255) NOT NULL,
caption VARCHAR(255) NOT NULL,
hint VARCHAR(255) NOT NULL,
INDEX Индекс 1 (id)
)
ENGINE=InnoDB
AUTO_INCREMENT=1;
Запрос для получения данных:
SET @origin='Find';
SET @LEVEL1='Application';
SET @LEVEL2='Form1';
SET @LEVEL3='btnFind';
/* Выдает первое значение, которое не NULL, то есть значение будет всегда,
но с разных уровней иерархии */
SELECT COALESCE(t3.caption, t2.caption, t1.caption)
FROM t_caption_ru t1
LEFT JOIN t_caption_ru t2 ON (t2.parent_id=t1.id AND t2.owner @LEVEL22)
LEFT JOIN t_caption_ru t3 ON (t3.parent_id=t2.id AND t3.owner @LEVEL33)
WHERE
(t1.owner = @LEVEL1 AND t1.origin = @origin) or
(t2.origin = @origin) or
(t3.origin = @origin)
Комментарии (4)
KirmiziTas
00.00.0000 00:00+1Глубина иерархии такого справочника не ограничена
Тогда нужен не COALESCE а рекурсивный запрос.
Naf2000
00.00.0000 00:00+2Моделей иерархии в РСУБД достаточно много, указанная Вами - самая простая в реализации, но возможно не самая оптимальная в эксплуатации. http://www.codenet.ru/db/other/trees/
-
Всегда ли надо заменять на более "общую" информацию? Пример иерархии Предприятие - Отдел - Сотрудник. Вы запрашиваете адрес сотрудника, а получаете адрес подразделения или предприятия, запрашиваете ИНН сотрудника - получаете ИНН предприятия, где он работает. Мне кажется это будет даже хуже, чем отсутствие информации.
dopusteam
Как понять, вернулось запрашиваемое значение или родительское?
Что если справочник вообще пустой или нет никакого родителя? Тогда значение не вернётся, а значит - значение возвращается не всегда
yumata Автор
Ну это-же "мысли по-поводу", а не готовое приложение...
Можно добавить значение по-умолчанию можно еще много чего.