Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.147.48.212] |
|
Данный раздел предназначается для обсуждения вопросов использования баз данных, за исключением составления запросов на SQL. Для этого выделен специальный раздел. Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ. |
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|||||||||||||||||||||
|
Доброго времени суток!
Столкнулся с вопросом хранения в БД иерархической информации. Информация представляет собой бухгалтерский отчет, типа:
И т.д. Все суммируется в группах, по строкам и столбцам. Как организовать хранение такой штуки? Заранее спасибо. |
Сообщ.
#2
,
|
|
|
Насколько я понимаю, структура дерева счетов меняется крайне редко, зато нужно очень часто искать потомков узла (всех или один уровень) и собирать по ним статистику. Также для оптимизации (кэширования) подсчетов пригодится поиск всех узлов-предков.
В этом случае идеально подходят вложенные множества (nested sets). Вкратце: для каждой записи хранятся два числа - левый (il) и правый (ir) индекс - которые отражают положение записи в иерархии. Назначаются они так: счетчик инициализируется единицей, затем дерево обходится в глубину слева направо; при каждом заходе в узел/лист "сверху" в его il пишется текущее значение счетчика и счетчик увеличивается; при каждом выходе из узла/листа "наверх" в его ir записывается текущее значение счетчика и счетчик увеличивается. В результате получается, что для каждой записи ее il больше il любого предка, а ее ir меньше ir любого предка. Также можно хранить в записи уровень ее вложенности и флаг, показывающий, является ли запись листом (а значит, хранит реальное число) или промежуточным узлом (а значит, нужно считать). В прстейшем случае суммы по строке и по столбцу не хранятся в БД, а высчитываются "на лету", но тогда требуется лишний SQL-запрос, и БД выполняет не очень-то нужную работу. Лучше кэшировать эти суммы в узлах. Если какое-либо число в листе изменилось, то пересчитываем сумму строки и для всех узлов-предков выставляем флаг "кэш невалиден". Если видим, что кэшированные данные в узле невалидны, то в транзакции считаем суммы потомков-листьев, пишем результат в узел и помечаем данные как валидные. |
Сообщ.
#4
,
|
|
|
Думаю, в данном конкретном случае (бух. отчёт) использование nested set избыточно. Вполне достаточно хранить материализованный путь узла (в примере структуры - поле Номер).
|
Сообщ.
#5
,
|
|
|
Цитата Akina @ хранить материализованный путь узла Могут быть варианты.Например, узел содержит несколько балансовых или внебалансовых (забалансовых) счетов. |
Сообщ.
#6
,
|
|
|
Для меня всё, что ты сказал - китайская грамота... но не вижу сложностей, если у какого-то узла несколько потомков. Лишь бы не было сетки.
|
Сообщ.
#7
,
|
|
|
Цитата Akina @ но не вижу сложностей, если у какого-то узла несколько потомков. Классическое дерево. Цитата Akina @ Для меня всё, что ты сказал - китайская грамота... Если это отчет и его надо хранить то нет проблем, но если надо вычислять - то ой. Например в пункте 1.1.1 сумма может складываться из 1000 счетов по которым прошли 1 000 000 транзакций за квартал (по каждому). Добавлено Цитата AVA12 @ В этом случае идеально подходят вложенные множества (nested sets). Достаточно ввести поле parent которое хранит выше стоящий id если есть, если нет то он сам по себе (1). |
Сообщ.
#8
,
|
|
|
Цитата Bas @ Например в пункте 1.1.1 сумма может складываться из 1000 счетов по которым прошли 1 000 000 транзакций за квартал (по каждому). Ну и что? какая разница, в сете оно хранится или на материализации? один хрен миллион сумм плюсить. Конечно, в сете группить попроще, но тоже не сахар - тут скорее всего наибольший эффект даст сегментация или кластеризация по путям. А ещё лучше - предрасчёты по минимальной (или даже не минимальной - но это усложнит хранимую логику) единице дискретизации по времени. |
Сообщ.
#9
,
|
|
|
Akina, мы залезли глубоко.
Keeper89, надо просто сохранить отчет, он не просил помощи в расчете |
Сообщ.
#10
,
|
|
|
Ну и что? ТС ответ получил. Во всяком случае не возмущается и в оффтопе нас не обвиняет - чё не потрындеть-то?
|
Сообщ.
#11
,
|
|
|
Цитата Bas @ Достаточно ввести поле parent которое хранит выше стоящий id если есть, если нет то он сам по себе (1). Для удобства еще "ПОЛНЫЙ НОМЕР СЧЕТА" в дереве счетов хранить неплохо. |
Сообщ.
#12
,
|
|
|
Павел Калугин
А смысл? материализованный путь это покрывает. Главное - не вешать абстрактные выравнивающие хвосты из нулей. А нестедсету это так и вовсе сиренево... |
Сообщ.
#13
,
|
|
|
Всем спасибо, ответы поизучаю!
|
Сообщ.
#14
,
|
|
|
Akina чтобы при необходимости просто показать полный номер счета не "разматывая" все дерево вверх
Отчеты "подпрыгивают и взлетают" |
Сообщ.
#15
,
|
|
|
Павел Калугин
Так полный номер и есть материализованный путь... |