Как создать вложенные категории в базе данных?

Я делаю видео-сайт, где будут вложены категории:

например Программирование -> Язык C -> Видео MIT -> Программирование видео 1 -> Язык C -> Стэнфордское видео -> Программирование видео 1 -> Python -> Видео 1

Эти категории и подкатегории будут создаваться пользователями на лету. Мне нужно будет показать их по мере того, как люди создают их в виде меню с возможностью навигации, чтобы люди могли легко просматривать коллекцию.

Может ли кто-нибудь помочь мне с тем, как я могу создать такую ​​базу данных?


person MathOldTimer    schedule 29.05.2009    source источник


Ответы (6)


Quassnoi сказал:

Вы должны использовать либо вложенные наборы, либо родительско-дочерние модели.

Раньше я реализовывал их оба. Что я могу сказать:

Используйте архитектуру вложенных наборов, если ваша таблица категорий не меняется часто, потому что в предложении select это быстро и с помощью всего одного запроса вы можете получить всю ветвь иерархии для данной записи. Но в предложении вставки или обновления требуется больше времени, чем у родительской дочерней модели, чтобы обновить левое и правое (или нижнее и верхнее в приведенном ниже примере) поля.

Еще один момент, довольно тривиальный, я должен признать, но:
Очень сложно вручную изменить иерархию непосредственно в базе данных (это могло произойти во время разработки). Итак, не забудьте сначала реализовать интерфейс для игры с вложенным набором (изменение родительского узла, перемещение узла ветки, удаление узла или всей ветки и т. Д.)

Вот две статьи на эту тему:

И последнее, я не пробовал, но где-то читал, что во вложенной таблице множеств может быть более одного дерева, я имею в виду несколько корней.

person Community    schedule 29.05.2009

Составьте таблицу категорий со следующими полями:

  • CategoryID - целое число
  • CategoryName - String / Varchar / Что угодно
  • ParentID - целое число

Затем ваш ParentID будет ссылаться на CategoryID своего родителя.

Пример:

CategoryID CategoryName ParentID
---------------------------------
1          Dog          NULL
2          Cat          NULL
3          Poodle       1
4          Dachsund     1
5          Persian      2
6          Toy Poodle   3
person TheTXI    schedule 29.05.2009
comment
Как мне построить запрос для создания навигации из такой таблицы? Есть простой способ? - person MathOldTimer; 29.05.2009
comment
Джейк: Я не знаю, как бы вы сделали свою собственную навигацию, но стандартным способом было бы сначала отобразить один уровень (например, верхний уровень), используя запрос вроде select * from tblCategories, где ParentID равен NULL, чтобы вы получили Собака и кошка. Затем, когда вы нажмете на собаку, вы можете перейти на следующий уровень, запросив Select * from tblCategories, где ParentID = 1, потому что 1 - это идентификатор категории Dog. И затем вы продолжаете таким же образом, чем дальше сверляете. - person TheTXI; 29.05.2009

Из примера в вашем вопросе похоже, что вы хотите, чтобы у данной категории было несколько родителей (например, «Видео MIT -> Программирование видео 1», а также «Видео -> Программирование видео 1»), в этом случае простого добавления столбца ParentID будет недостаточно.

Я бы рекомендовал создать две таблицы: простую таблицу категорий со столбцами CategoryID и CategoryName и отдельную таблицу CategoryRelationships со столбцами ParentCategoryID и ChildCategoryID. Таким образом, вы можете указать столько родительско-дочерних отношений, сколько хотите для любой конкретной категории. Можно было бы даже использовать эту модель для создания двойных отношений, когда две категории одновременно являются родительскими и дочерними друг для друга. (Не знаю, как хорошо использовать этот сценарий, но, по крайней мере, он показывает, насколько гибкой является модель.)

person Dan Tao    schedule 29.05.2009
comment
Спасибо! Это именно то, что я хотел. В качестве примера я хотел бы, чтобы видео-учебник по ассемблерному языку был указан как в основах обратного проектирования, так и в языках программирования. - person MathOldTimer; 29.05.2009

Вы должны использовать либо nested sets, либо parent-child модели.

Parent-child:

typeid parent name

1      0      Buyers
2      0      Sellers
3      0      Referee
4      1      Electrical
5      1      Mechanic
SELECT  *
FROM    mytable
WHERE   group IN
        (
        SELECT  typeid
        FROM    group_types
        START WITH
                typeid = 1
        CONNECT BY
                parent = PRIOR typeid
        )

выберут всех покупателей в Oracle.

Nested sets:

typeid lower  upper  Name
1      1      2      Buyers
2      3      3      Sellers
3      4      4      Referee
4      1      1      Electrical
5      2      2      Mechanic
SELECT  *
FROM    group_types
JOIN    mytable
ON      group BETWEEN lower AND upper
WHERE   typeid = 1

отберет всех покупателей в любой базе.

Дополнительные сведения см. В этом ответе.

Nested sets проще запросить, но сложнее обновить и сложнее построить древовидную структуру.

person Quassnoi    schedule 29.05.2009

Вам нужны базовые родительско-дочерние отношения:

Category (ID: int, ParentID: nullable int, Name: nvarchar(1000))
person Anton Gogolev    schedule 29.05.2009

Лучший способ сохранить parent_id таблицы - вложить его в ID, например

100000 Программирование 110000 Язык C 111000 Видео 1 Программирование 111100 Язык C 111110 Стэнфордское видео

и т. д. все, что вам нужно, это сценарий для обработки идентификатора, чтобы первая цифра представляла категорию верхнего уровня и так далее, когда вы идете глубже по иерархии

person Community    schedule 28.07.2009
comment
Это довольно интересный способ. У вас есть идеи, как запрашивать такие данные? - person Subliminal Hash; 27.05.2016
comment
Разве это не ограничивает вас 10 предметами верхнего уровня 0-9? В чем причина использования нулей, вы используете заданное количество целых чисел, которое ограничивает количество возможных потомков? Как бы вы вставляли новые элементы и обновляли их? - person Robert Went; 07.01.2018