У меня есть типовой вопрос, за которым следует вопрос о представлении в отдельном сообщении SO, на который я буду ссылаться при его создании.Я делаю два сообщения, поэтому я могу сделать два приема.
Теперь давайте начнем с предположения, что у меня есть следующая схема.Это упрощенная версия реальной схемы, которую я разрабатываю, с опущенными нерелевантными столбцами.Имена были изменены, чтобы защитить невинных, и моя работа.
tree
имеет следующие атрибуты.
tree.id
tree.dob
tree.height
tree.forestid
forestid
- это внешний ключ к таблице forest
,это просто способ агрегировать несколько tree
строк.В нем есть столбец id
и несколько столбцов метаданных.
tree
и forest
имеют потенциально много строк treedata
.treedata
содержит
treedata.value
treedata.treeid
treedata.forestid
treedata.treeid и treedata.forestid ограничены так, что один из двух должен быть нулевым.
Если tree.forestid не равно нулю, то связь междуtreedata и tree - это многие ко многим, а forest - это таблица линкеров.В противном случае, отношения между деревом и treedata один ко многим.Для моего приложения очень важно, чтобы пользователь мог на лету с помощью пользовательского интерфейса группировать деревья в леса на лету, задавать значение treedata.value для всего леса, а также иметь возможность работать с отдельными деревьями.Теперь я могу придумать пару способов представить это.Один из них - сказать, что каждое дерево имеет лес и является лесом, по крайней мере, 1-го размера. Тогда отношение всегда много ко многим.Другой способ - предоставить денормализованное представление по линиям
select tree.*, treedata.*
from tree, treedata
where tree.id = treedata.treeid
union
select tree.*, treedata.*,
from tree, treedata
where tree.forestid = treedata.forestid.
Еще один третий способ - создать столбец forestid
в tree
и полностью удалить таблицу forest
.По этому пути я вижу трудности в получении гарантий ACID в отношении правильного приращения tree.forestid
.Также существует вероятность того, что леса должны содержать свои собственные метаданные.Мне бы хотелось услышать больше способов представить это, а также узнать мнение более опытных специалистов по базам данных о том, какой путь предпочтительнее, и высших оценок, если вы объясните, почему вы так думаете, приведя примеры из собственного опыта.
Ответ на предложение Мартина Дома о таблице TreeComposite:
Спасибо за ваш ответ.Я хотел дать предложение TreeComposite за день до кипения, прежде чем ответить.Во-первых, ваш путь моделирует отношения, которые я выражаю в нормальной форме, так что да, я думаю, вы понимаете вопрос.Однако, я думаю, что сделал глупую ошибку, назвав свои таблицы Tree и Forest: потому что леса не должны быть рекурсивно соединяемыми друг с другом.Они не деревья информатики.Они просто кора и веточка деревьев.Модель парентид, хотя она все еще представляет то, что мне нужно в нормальной форме (это обобщение того, что мне нужно), и хотя она имеет преимущество в том, что деревья и леса теперь «одно и то же», что на первый взгляд является сложным выигрышемБоюсь, что в почве это будет запутанный беспорядок.
Проблема в том, что независимо от того, называются ли они одной и той же в моей модели, они не совпадают с моим контроллером илиПосмотреть.Например, TreeComposite с дочерними узлами, вероятно, будет иметь хотя бы атрибут, для которого каждый узел будет иметь отдельное значение.В этом случае мне нужно использовать другой виджет в моем представлении для отображения нескольких значений для атрибута.Иными словами, мне нужно иметь возможность отображать каждый TreeComposite, который является его собственным родителем, в виде одной строки, и то, как эта строка выглядит, зависит от того, есть ли у TreeComposite дочерние элементы.
Итак, первое, что я должен сделать после извлечения TreeComposite из моей модели, это решить, действительно ли это дерево или лес. Зачем это делать, когда я могу хранить его в обычной форме в виде дерева и леса напрямую, тем самым упрощая мои представления и контроллеры без ущерба для моей модели? Поиск TreeData также осложняется отношениями родитель-потомок. Мне нужно подключиться через N номеров TreeComposites, пока я не найду корневой узел, а затем искать TreeData, указывающую на корневой узел. Это уничтожает данные. Между тем, если у меня есть дерево с ForestID и я хочу получить данные этого дерева, мне вообще не нужно смотреть на таблицу Forest. Я могу сделать прямое соединение с иностранным ключом <-> к TreeData. (where Tree.ForestID = TreeData.ForestID
).